Ben Bolker wrote:> (not sure whether this is better for R-devel or R-help ...)
>
>
Hardcore debugging is usually better off in R-devel. I'm leaving it in
R-help though.
> I am currently trying to debug someone else's package (they're
> not available at the moment, and I would like it to work *now*),
> which among other things allocates memory for a persistent
> buffer that gets used by various functions.
>
> The first symptoms of a problem were that some things just
> didn't work under Windows but were (apparently) fine on Linux.
> I don't have all the development tools installed for Windows, so
> I started messing around under Linux, adding Rprintf() statements
> to the main code.
>
> Once I did that, strange pointer-error-like inconsistencies started
> appearing -- e.g., the properties of some of the persistent variables
> would change if I did debug(function). I'm wondering if anyone
> has any tips on how to tackle this -- figure out how to use valgrind?
> Do straight source-level debugging (R -d gdb etc.) and look for
> obvious problems? The package uses malloc/realloc rather than
> Calloc/Realloc -- does it make sense to go through the code
> replacing these all and see if that fixes the problem?
>
Valgrind is a good idea to try and as I recall it, the basic
incantations are not too hard to work out (now exactly where is it that
we wrote them down?). It only catches certain error types though, mostly
use of uninitialized data and read/write off the ends of allocated
blocks of memory.
If that doesn't catch it, you get to play with R -d gdb. However, my
experience is that line-by-line tracing is usually a dead end, unless
you have the trouble spot pretty well narrowed down.
Apart from that, my usual procedure would be
1) find a minimal script reproducing the issue and hang onto it. Or at
least as small as you can get it without losing the bug. Notice that any
change to either the script or R itself may allow the bug to run away
and hide somewhere else.
2) if memory corruption is involved, run under gdb, set a hardware
watchpoint on the relevant location (this gets a little tricky sometimes
because it might be outside the initial address space, in which case you
need to somehow run the code for a while, break to gdb, and then set the
watchpoint).
3) It is not unlikely that the watchpoint triggers several thousand
times before the relevant one. You can conditionalize it; a nice trick
is to use the gc_count.