You can do several things. On an unmodified 32-bit application in Windows you may be able to use DrMemory.
(I assume you already configured your compiler to issue all the warnings it can. Never understimate the potential troubles hiding behind a "warning").
You might also port your program to Linux (on a VMware virtual machine, maybe) and use Valgrind. Then as soon as you run the program, you will be informed of an array of possible mistakes in the code, complete with file name, line number and description.
Finally, there are "memory checking libraries" (eFence, but there are others) that you will compile/link with your ANSI C program, and will replace most ways in which you can mess up with memory. Sometimes you will also have to include calls to some check function, so that your code becomes something like:
CHECKPOINT
at = getAnotherTree(i++, info);
CHECKPOINT
Then, if you perform a flawed standard call in getAnotherTree()
, you will get an error such as
treebuild.c at line 597: strcpy: attempt to copy 192 bytes into 128-byte buffer
ABORTING
and if you do that by hand, for example with
for (i = 0; i < bufSize; i++) {
buffer[i] = 0;
}
then the second checkpoint will throw an error such as
treebuild.c at line 1080: CHECKPOINT FAILURE
thereby pinpointing the source of the error to something in the program flow between the last known good checkpoint and the failing one.