I have a number of custom allocators that use the same techniques, with some improvements.
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.
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.
With this a good number of overruns and use after free bugs have been found.
Mostly used this technique on windows with delphi, on linux i prefer valgrind.
Ah. It sounded like you were mapping 2 4k pages for the allocation itself, aligning the allocation at the end of that 2-page span, and then mapping the following page and marking it as denied.
I wasn't the original poster, that was just my impression of the scheme. I could have misunderstood, in which case I don't have any alternate theories for what that second page is for :-)
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.
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.
With this a good number of overruns and use after free bugs have been found.
Mostly used this technique on windows with delphi, on linux i prefer valgrind.