When the C code accesses memory that it does not own, one often gets the
symptoms that you describe. Finding these can be very difficult. There are
two
tools that I start with.
1. Replace your .C call with .Cdebug. (This is a part of Splus). Do this
for
a case that does not fail, but is large enough to be "close to" failure mode.
This routines pads out all of the vectors passed to the C routine with zeros,
then checks on return that none of these extra zeros have been perturbed. If
any have, this often gives a good pointer to what part of the C code is in
error. A common one is to have a "work" vector tha was not quite big enough.
2. About 90% of the time the call above doesn't work. If you have access to
a
good C debugger/memory-checker, replace your .C call with a call to the CC
function, given below. It creates a main routine which is almost all data
statements, followed by a call to your C routine that has exactly the arguments
that S will be calling it with. Change any calls to the S memory routines (eg
S_alloc) to the corresponding C ones (alloc), and link the routine to your dll
outside of S. Now you have a stand alone mainline, that can be run under your
debugger environment; set it up for strict memory checking and go.
3. In unix, I can run S through the memory checking debugger. (The setup was
compliments of Bill Dunlap). I don't use Windows, however, and have no insight
there.
Terry Therneau
-----------------------
CC <- function(subroutine, ..., copy, NAOK = F)
{
assign("file", paste("D", subroutine, ".c", sep = ""), frame = 1)
assign("out", function(...)
cat(..., file = file, append = T), frame = 1)
put <- function(type, name, data)
{
out(paste(type, " ", name, "[]", sep = ""), "= {")
out(data, sep = ",", fill = 60, labels = "\t")
out("};\n\n")
}
unix(paste("rm -f", file))
args <- list(...)
index <- seq(along = args)
n <- names(args)
if(length(n) == 0)
n <- rep("", length(args))
if(length(n) > 0)
n <- ifelse(n == "", paste("arg", index, sep = ""), n)
for(i in index)
switch(storage.mode(args[[i]]),
character = put("static char *", n[i], paste("\"",
args[[i]], "\"", sep = "")),
integer = put("static long", n[i], args[[i]]),
single = put("static float", n[i], args[[i]]),
double = put("static double", n[i], args[[i]]),
logical = put("static long", n[i], args[[i]]),
stop(paste("Unknown mode", m[i], "for argument", i)))
out("main() {\n", subroutine, "(", paste(n, collapse = ", "), ");\n}\n",
sep = "")
}
|