HeapAgent






Comparison of HeapAgent™ and BoundsChecker Standard Edition™

The following table compares the heap error detection and diagnosis features in HeapAgent 2.1 with those in NuMega's BoundsChecker 3.01, Standard Edition. This comparison reflects only heap-debugging features and does not review the non-heap-related features that BoundsChecker provides, such as detection of API parameter errors. HeapAgent is a dedicated heap-error detection and diagnosis tool and doesn't attempt to provide any other functionality. While there is some overlap in the functionality of HeapAgent and BoundsChecker, the two products mostly serve complementary purposes.

BoundsChecker is external to your application and watches the interface between your application, Windows, and portions of the C runtime library. You must run your application from within BoundsChecker for it to detect errors, and you cannot access your source debugger while BoundsChecker is running. HeapAgent, on the other hand, runs automatically every time you launch your app, even from the Visual C++ debugger. HeapAgent's heap error detection is more comprehensive than BoundsChecker's, but HeapAgent doesn't look at the interface between your application and the operating system.

HeapAgent checks for errors in a background thread, whereas BoundsChecker checks during each API call your application performs. As a result, HeapAgent is able to perform overwrite checking continuously with negligible impact (less than 50%) on your application's performance. If you turn overwrite checking on in BoundsChecker (overwrite checking is on only when the BoundsChecker error-detection setting is at "Maximum"), your application will slow considerably, possibly 100x or more slower, depending on the size of your heap.

Note: To display detailed information on an individual item, choose the number of the item.

Errors detected                                   BoundsChecker  HeapAgent
1. Overwrites beyond end of allocated blocks Yes Yes 2. Underwrites before beginning of allocated blocks No Yes 3. Overwrites over internal heap data structures No Yes 4. Wild overwrites Some Some 5. References to data in uninitialized objects No Yes 6. Writes into freed objects No Yes 7. References to data in free objects No Yes 8. Double-frees Some Yes 9. References to non-shared data owned by another task No Yes 10. Changes to data in objects marked read-only No Yes 11. Premature frees No Yes 12. Unexpected resizing of objects No Yes 13. Invalid parameters to heap-related calls Yes Yes 14. Retained references to reallocated memory No Yes 15. Leakage - objects not freed at end of program Yes Yes 16. Leakage - at other points in program No Yes Error reporting
17. File name and line number identifying the call at which the error was detected Yes Yes 18. File name and line number identifying the call that allocated the object Some Yes 19. Pass count at file/line to pinpoint specific object No Yes 20. Unique identifier for each object No Yes 21. Object parameters, including size, contents, and address No Yes 22. User-defined object checkpoints No Yes Error diagnosis
23. Browse source code associated with the detected error Yes Yes 24. Dump and browse contents of memory related to the error No Yes 25. Format memory contents as ASCII, int, float, pointer, etc. No Yes 26. Select any byte of memory and display the source that allocated it No Yes 27. Select any source line and display the objects it allocated No Yes 28. Set breakpoints on user-specified heap events No Yes 29. Change error detection settings based on user-specified heap events No Yes 30. Break to your compiler-supplied debugger from any error No Yes

Details on the HeapAgent/BoundsChecker comparison

1, 2. To detect overwrites and underwrites, HeapAgent uses variable-size leading and trailing guards around objects. You can specify both the guard size and the signature value. HeapAgent includes several options for performing overwrite checks, including checking in a background thread, explicit checks by choosing Find Overwrites menu option, checks during heap calls, and checks by calling the HeapAgent API directly.

BoundsChecker uses trailing guards only. The guard value is fixed. Overwrites are detected only when an overwritten object is freed or, optionally, during any call to a routine watched by BoundsChecker.

3. HeapAgent implements the heap and, therefore, can detect corruption of internal heap control information.

4. In HeapAgent, you can set the guard size and value. If you increase the guard size, you increase the ratio of guard bytes to data bytes in the heap and, thereby, increase the likelihood that a wild overwrite will be detected. Moreover, HeapAgent places guards both before and after blocks.

5. HeapAgent fills new objects with a user-definable in-use fill value, which prevents programs from relying on initial values such as zero. If you read a pointer from uninitialized memory and dereference that pointer, HeapAgent intercepts the resulting GPF and reports both the responsible line of code and details of the allocation that was read. BoundsChecker does not detect references to uninitialized memory.

6. HeapAgent fills freed objects with a user-definable free fill value and detects any change in the value.

7. The default HeapAgent free fill value is an invalid pointer value (and obviously a bad value in general), so attempts to dereference a pointer stored in a freed block will cause a GP fault. HeapAgent intercepts and reports GPFs, showing you where the dereference occurred and where the object was freed.

8. When your program frees an object, HeapAgent's "deferred freeing" marks the object as free. However, the corresponding memory is not immediately recycled for reuse, which guarantees that double-frees are detected. (You can specify how long HeapAgent withholds memory from the free pool before recycling it.) BoundsChecker detects double frees only if the previously freed block hasn't already been recycled. Most compiler allocators immediately recycle free memory, so BoundsChecker will rarely catch double-frees and other references to free memory. This is very important since one of the most insidious types of heap errors is a read or write of a dangling pointer - one that was previously freed.

9. HeapAgent can detect invalid references from another task in 16-bit Windows. (These references are prohibited by the OS in 32-bit Windows.)

10. In HeapAgent, you can mark an object as read-only. Any subsequent change to the object is reported as an error.

11. In HeapAgent, you can mark an object as no-free. Any subsequent attempt to free the object is reported as an error.

12. In HeapAgent, you can mark any object as no-realloc. Any subsequent attempt to resize the object is reported as an error.

13. If you pass an invalid parameter to a heap-related function, HeapAgent immediately reports a parameter error. HeapAgent also reports an error if you pass invalid flags or buffers to the HeapAgent debugging APIs.

14. In HeapAgent, you can specify that realloc always move an object to a new place in memory rather than try to resize it in place. The old location is then filled with the free fill value. Thereafter, if your program frees or references the object at the old address, HeapAgent reports this as an error. With BoundsChecker, retained references to realloc'd objects are not caught in the common case where the C runtime realloc implementation returns the same address it was passed.

15. For each allocation, HeapAgent reports an allocation number (see #20) and a pass count. You can then set a breakpoint in HeapAgent on a subsequent run when this object is created. This lets you break in the debugger at the exact call to new or malloc that creates the leaking object, allowing you to easily diagnose the cause of leakage.

16. With HeapAgent, you can find leakage at any point in your application by filtering objects for a broad range of properties, including file, line number, function, object contents, address, pass count, and so on. You can also use checkpoint tags to group objects and then check at a future point for objects with a given checkpoint. See also #15.

17. To get file and line information, BoundsChecker requires a debug build of your program. HeapAgent requires either debugging information or a recompile with the HeapAgent header file, whichever is more convenient for you.

18. For every error, HeapAgent reports the creation site of the related object, which helps you identify the data related to the error. BoundsChecker only reports the creation site for certain errors. See also #15.

19. If a source file and line allocated more than one object, HeapAgent's pass count ties an error to a specific object.

20. HeapAgent assigns a sequential number to each object. The allocation number uniquely identifies each object and, therefore, a specific point in time in the execution of the application. (Pointer addresses aren't unique, because they're recycled during a session.)

21. For each error, HeapAgent reports the function that caused or that detected the error, as well as the parameters that were passed to the function.

22. A checkpoint is a user-defined number that identifies the group an object belongs to. By default, all objects have a checkpoint value of 1, but you can change the checkpoint value either manually from the Debug Settings dialog box or an API call, or automatically with an agent. Checkpoints let you group objects in any way that you find useful; this can be valuable for helping to identifying leakage and overwrites in particular sections of code, for example.

23. HeapAgent keeps track of everything that happens in the heap and understands the association between the error, your source code, and the heap. As a result, you can navigate from an error to the source related to the error and from the source line to all current objects that the source line allocated.

24. When HeapAgent detects an error, you can jump directly from the Error Report dialog box to the Dump Browser, where you can browse the memory related to the error. When BoundsChecker finds an error, you cannot access your debugger and BoundsChecker doesn't provide any means of examining the contents of memory, local variables, or global variables to diagnose the error.

25. In the HeapAgent Dump Browser, you can display individual bytes or groups of bytes in the following formats: ASCII, C string, binary, octal, signed or unsigned decimal, float, hex, or pointer.

26. In HeapAgent, you can jump from any address directly to the object at that address or to the source code that allocated the object. You can also follow pointers to other memory locations and backtrace to the original location.

27. From the HeapAgent Source Browser, you can select a line of source code and display an Allocation Browser containing detailed information on every object allocated by the selected line of code.

28. In HeapAgent, you can select objects and set breakpoints that will cause your application to break to HeapAgent when those objects are allocated, resized or freed.

29. In HeapAgent, you can define "intelligent agents" to help diagnose elusive bugs. Each agent includes two user-defined parts: a strategic heap-related "condition" (IF), such as all calls to new from a particular source file; and a corresponding "action" (THEN), such as checking for leakage or changing HeapAgent's debugging settings. Agents eliminate the need to dig through your source, insert debugging code, and recompile your application.

30. HeapAgent runs alongside your compiler-supplied or third-party debugger. You can break from an error to your source debugger, where you can look at a stack backtrace, view local variable contents, and so on. BoundsChecker can't be run simultaneously with the Microsoft or with the Borland compiler-supplied debugger or, for that matter, with any debugger except NuMega's own SoftIce.