Without having looked at OpenBSD's implementation, just unmapping free pages does not mean you catch all writes to free()d memory. If a block is smaller than the pagesize, which many times is the case, a page will likely still hold other objects so it wont be unmapped and therefor not trigger a segfault.<p>Valgrind is my tool of choice to find invalid reads or writes. It catches all of them plus it gives you nice information like a stacktrace.<p>What OpenBSD's implementation of malloc() does get you though is improved coping with memory fragmentation.
Allocating memory in a continously heap brings lots of pain - jemalloc (which is the default allocator in FreeBSD and NetBSD) solves this nicely by also only using mmap() instead of sbrk() on Linux.<p>Note: I should have said "resource reclamation" instead of "fragmentation". See discussion with ajross below for details.
the windows heap manager can be configured to do this on a per-application basis using the 'gflags' utility.<p>it's a useful debugging tool. you're not assured that use-after-free is going to be tightly temporally coupled with the free (a lot of the time it is though) and as more time passes after free() the odds increase that the dangling virtual address is re-allocated.<p>it is also the enemy of performance. you should probably not run production things with the heap configured in this way.
I have a number of custom allocators that use the same techniques, with some improvements.<p>When space is cheap:
All allocations are two 4k pages
The returned pointer is alligned with the end of the buffer to detect overruns. (with a 16byte allignment)
The page following the alloc is always denied.
The space around the allocation is filled with flag values, and these are checked on free.
After free the pages are held in storage for a few thousand following allocations.<p>The variants of this allocator does things like only doing this for specific ranges of allocation sizes or only after a certain number of allocations.<p>With this a good number of overruns and use after free bugs have been found.<p>Mostly used this technique on windows with delphi, on linux i prefer valgrind.
Is this really different from the glibc malloc() implementation with MALLOC_CHECK_ set to 3?<p>> MALLOC_CHECK_ is designed to be tolerant against simple errors, such as double calls of free() with the same argument, or overruns of a single byte (off-by-one bugs). Not all such errors can be protected against, however, and memory leaks can result.<p>> If MALLOC_CHECK_ is set to 0, any detected heap corruption is silently ignored;<p>> if set to 1, a diagnostic message is printed on stderr;<p>> if set to 2, abort(3) is called immediately;<p>> if set to 3, a diagnostic message is printed on stderr and the program is aborted.