How to debug anomalous C memory/stack problems
Sorry I can't be specific with code, but the problems I am seeing are anomalous. Character string values seem to be getting changed depending on other, unrelated code. For example, the value of the argument that is passed around below will change merely depending on if I comment out one or two of the fprintf() calls! By the last fprintf() the value is typically completely empty (and no, I have checked to make sure I am not modifying the argument directly... all I have to do is comment out a fprintf() or add another fprintf() and the value of the string will change at certain points!):
static process_args(char *arg) {
/* debug */
fprintf(stderr, "Function arg is %s\n", arg);
...do a bunch of stuff including call another function that uses alloc()...
/* debug */
fprintf(stderr, "Function arg is now %s\n", arg);
}
int main(int argc, char *argv[]) {
char *my_arg;
... do a bunch of stuff ...
/* just to show you it's nothing to do with the argv array */
my_string = strdup(argv[1]);
/* debug */
fprintf(stderr, "Argument 1 is %s\n", my_string);
process_args(my_string);
}
There's more code all around, so I can't ask for someone to debug my program -- what I want to know is HOW can I debug why character strings like this are getting their memory changed or overwritten based on unrelated开发者_C百科 code. Is my memory limited? My stack too small? How do I tell? What else can I do to track down the issue? My program isn't huge, it's like a thousand lines of code give or take and a couple dynamically linked external libs, but nothing out of the ordinary.
HELP! TIA!
Simple:
- Learn to use Valgrind, specifically memcheck
- Learn to use GDB including break points and variable inspection
- Practice makes perfect.
That should sort it. Make sure you compile any libraries with the -g
option on GCC, which keeps debugging symbols so your debugging output makes more sense.
There are two cases to consider:
- The
arg
variable changes value between the start and finish ofprocess_args
. - The
arg
stays the same, but the string it points to is changed.
Your description and your code doesn't differentiate between the two, but it's important to know which of the two is actually happening.
This will reveal the answer:
fprintf(stderr, "Function arg is %s (%p)\n", arg, (void *)arg);
... do bunch of stuff ...
fprintf(stderr, "Function arg is now %s (%p)\n", arg, (void *)arg);
Most often arg
is not changing (i.e. you have case 2). If so, something is corrupting the string you've allocated. Valgrind, suggested already, but available only on Linux, AIX and MacOSX, has only a 50:50 chance of finding the problem. What you really want is a GDB watchpoint: set breakpoint at the start of process_args
, once hit, do (gdb) watch *(long*)arg
and continue
. GDB will stop when something writes to *arg
(it will actually stop on the next instruction). Then use (gdb) where
command to figure out what's happening.
If you actually have arg
changing its value (case 1), that may be harder to debug, and indicates stack corruption of some sort, or a violation of procedure calling conventions for your platform. Valgrind will likely not help at all with that. This is more consistent with the behavior you described: commenting out unrelated code causes the bug to shift.
I can't give any further advice on debugging case 1 though, since you haven't revealed what your actual platform is.
If you are writing user-level applications, Valgrind is a good choice to detect memory problems such as memory leaks, buffer overflow, etc. Here is a quick start guide: http://valgrind.org/docs/manual/QuickStart.html
You don't give your dev tools, but if you're like 90% of coders you're already using an IDE with a debugger which can handle this, no new tools required. Set a watch on the chunk of memory holding your strings, then step through your code and see when the strings get changed.
精彩评论