|
Kylix for Delphi programmers - Debugging Dynamic Memory |
|
If you read man malloc, you'll see that glibc checks the MALLOC_CHECK_ environment variable when a program starts. Normally (ie, when the MALLOC_CHECK_ environment variable is not set) misuses of dynamic memory like freeing a heap block (calling FreeMem) twice or writing past the end of allocated memory are not necessarily caught immediately. As with suballocator abuse, sometimes these errors generate exceptions and sometimes they don't. Obviously, the sooner a bug shows up, the better. If you set the MALLOC_CHECK_ environment variable to 1 before you run your program, glibc can detect common programming mistakes, and write a message to StdErr. If you set MALLOC_CHECK_ to 2, glibc will raise a SIGIOT. If you're running within the IDE, Kylix will stop your program and report the SIGIOT, but it will not map it to an Object Pascal exception. If you press F9 after receiving a SIGIOT, your program halts. If you have a copy of my book, the MallocCheck project in the ch8/Memory project group demonstrates this. (The two figures and the sample code in the paper is from this project.) If you run it in the normal (no MALLOC_CHECK_) environment, pressing the "Buffer Overrun" button causes no immediate problem (usually this depends on the state of the suballocator). Similarly, pressing the "Double Free" button may cause an immediate SIGSEGV, or it may cause a SIGSEGV when you try to close the application, or it may not cause any problem at all. However, if you bring up the Run > Parameters dialog, select the Environment Block tab, and use the New button to set MALLOC_CHECK_ to 1, you'll get very different behavior. When the program starts, you'll get a message on StdErr saying "malloc: using debugging hooks". When you press the Buffer Overrun or Double Free buttons, you'll get messages on StdErr about the mistakes these routines deliberately make. Similarly, if you use Run > Parameters to set MALLOC_CHECK_ to 2, you'll get a SIGIOT. Unfortunately, Kylix isn't able to show you which line generated the SIGIOT, but if setting MALLOC_CHECK_ to 1 or 2 reveals misuse of dynamic memory, you should find it reasonably straightforward to find where your error(s) is (are) by single-stepping and/or knocking out vast swatches of your application to pinpoint the offenders. Electric FenceLinux also includes the Electric Fence memory checker, which forces each and every malloc to live on its own hardware memory page. This catches just about every sort of misuse of dynamic memory, at the cost of making your programs run very slowly and consuming vast quantities of memory. If you suspect one of your programs is misusing dynamic memory, MALLOC_CHECK_ should be your first line of attack, because it won't slow your program down anywhere near as much as Electric Fence does. However, if MALLOC_CHECK_ doesn't report any suspicious behavior, you can run your program under Electric Fence by simply typing ef MyApp & instead of MyApp &. For example, MALLOC_CHECK_ can't detect suballocator abuse like the MallocCheck project's "Deref Freed" button generates but Electric Fence can. |