PRODUCT : Turbo C++ NUMBER : 810 VERSION : All OS : DOS DATE : October 19, 1993 PAGE : 1/2 TITLE : Tracking down crash bugs Tracking down crash problems in a program can often be quite difficult. Here are a few tips to speed up the process. First, it depends on what memory model is being used. It is far easier to crash the machine in a large data model (Compact, Large, and Huge) than in a small data model (Tiny, Small, and Medium.) In the small data models, the easiest way to crash the machine is with a stack or heap overflow, or stack corruption. Data corruption normally does not have this effect since in the small data model, only the 64K data segment can be corrupted. But since the data segment also includes the stack, and the stack and the heap grow into each other, it possible to corrupt the stack. Corruption of the stack eventually leads to sending the CPU into no-mans land by corrupting return addresses of functions. In the large data models, crashing the machine is easy, since writing to a NULL far pointer trashes the interrupt table, and writing to a bad pointer can write anywhere in memory, including the code segments of the program and DOS internals. Other possibilities include array indexes out of bounds, which can easily cause heap corruption if the array was dynamically allocated. So, what can be done about it? First, check the easy things: Make sure that the program is compiled with all warning messages turned on. Resolve all warning messages, unless they are of no consequence and can safely be ignored (like "'parameter' is never used in function 'func'") Messages like "Non-portable pointer conversion" should always be resolved. Make sure that all dynamic memory allocation requests are checked for a NULL return value and that the file is #included ( can be used in the small data models.) Next, try increasing the stack size. (See the HELPME!.DOC file for instructions on how to do this.) This can sometimes identify a possible stack overflow. Also, place calls to the function heapcheck() at strategic points in the code. If there is a heap corruption problem this can give you some idea of when it happened. Judicious use of breakpoints can also help localize the problem. Run the program in Turbo Debugger with a breakpoint set for "Change Memory Global" at address 0:0,4 to see if the start of the interrupt table is being corrupted. (If you are using a small data model, this step is meaningless. NULL pointer assignments are identified by the exit code running a checksum on the beginning of the data segment of the program when it ends. If the checksum fails, a "Null pointer assignment" message is printed. You can catch the offender in this case by changing the above address to ds:0,4) PRODUCT : Turbo C++ NUMBER : 810 VERSION : All OS : DOS DATE : October 19, 1993 PAGE : 2/2 TITLE : Tracking down crash bugs Once the problem has been localized, either with the aforementioned techniques, or it was consistent enough to make identification easy, start in with the heavy artillery. If the interrupt table is being walked on, you can identify the code responsible with the aforementioned breakpoint. Work backwards from there. If practical, try stepping through the section that is believed to be responsible. Familiarity with assembly language can be quite helpful, as the absolute path of the CPU can be traced with Turbo Debugger's CPU Window, including the inside of library functions, and into interrupts, if necessary. Try to identify when the program is working on bad data, or has bad code segments indicating memory corruption. If a 386 machine is available, TD386 can often be of help in tracing these kinds of problems. DISCLAIMER: You have the right to use this technical information subject to the terms of the No-Nonsense License Statement that you received with the Borland product to which this information pertains.