Add debug mode options to skip block fill patterns and checksums (lightweight profiling mode)#92
Conversation
|
Thanks for the suggestions. It certainly makes sense to add these debug mode tweaks to FastMM_DebugModeOptions. As you rightly point out it would make it necessary to store the options that were in effect in the debug header, but fortunately there's a perfect spot for it - the TFastMM_DebugBlockHeader.ReservedSpace2 field. A risk with allowing the disabling of checksums is that if a memory corruption happens to clear the flag that indicates whether the block has checksums then that corruption could go unnoticed (even though the block actually has checksums). At the very least I would want to replace the checksums with magic numbers to serve as header and footer guards against buffer overruns. I've got some ideas for other options I would like to add to FastMM_DebugModeOptions. I'm probably not going to be able to get to it during the week, but I'll try to make time over the weekend. |
|
Good point regarding the flag-corruption risk - I've updated the PR with your magic number suggestion (6427e64): blocks allocated with Besides catching buffer overruns into the debug header/footer, the guards cross-check the Feel free to reshape any of this to fit the additional options you have in mind - happy to adjust the PR as well. |
6427e64 to
4592a96
Compare
…htweight profiling mode) Adds two options to TFastMM_DebugModeOption, extending the mechanism introduced for pleriche#82: - dmoNoBlockFillPatterns: skip the freed/allocated block fill patterns. While FastMM_Begin/EndEraseAllocatedBlockContent or FastMM_Begin/EndEraseFreedBlockContent are active, blocks are still erased regardless of this option. - dmoNoBlockCheckSums: skip the header/footer checksum calculation and verification. With both options enabled, debug mode still maintains the full debug block headers (allocation number, allocating/freeing thread, timestamps and the allocation/free stack traces), but skips the expensive per- operation work. This makes it practical to keep debug mode enabled for allocation profiling or leak analysis in scenarios where full debug mode would be too slow, at the cost of forgoing the use-after-free and corruption detection. 200k GetMem/FreeMem pairs of 4000 bytes in debug mode drop from ~110 ms to under the timer resolution (Delphi 13.1, Win64). The features actually applied to each block are recorded in the block header (in the previously reserved byte, now DebugFeatureFlags), and all verification sites consult the block's own flags rather than the currently active options. The options can thus be changed while debug mode is active without invalidating existing blocks - blocks allocated under different settings coexist safely.
…NoBlockCheckSums Addresses review feedback on the risk that a corruption clearing the has-checksums feature flag could mask a corrupted block: without checksums, the header and footer checksum slots now hold a fixed guard value (CDebugBlockNoCheckSumsGuardValue) that is verified wherever the checksums would have been verified. The guards catch buffer overruns into the debug header/footer, and they also cross-check the DebugFeatureFlags byte itself: if a corruption flips the checksums feature flag in either direction, the slot content no longer matches what the flag promises (a real checksum practically never equals the guard value and vice versa), so the corruption is still reported. Verified in both directions, plus the full option test matrix, with Delphi 10 Seattle and 13.1 (Win32+Win64).
4592a96 to
231e185
Compare
This extends the
FastMM_DebugModeOptionsmechanism from #82 with two options that skip the expensive parts of debug mode while keeping the debug block headers fully populated:dmoNoBlockFillPatterns- skip the freed/allocated block fill patterns. WhileFastMM_Begin/EndEraseAllocatedBlockContentorFastMM_Begin/EndEraseFreedBlockContentare active, blocks are still erased regardless of this option, so the security-oriented erase feature keeps its guarantees.dmoNoBlockCheckSums- skip the header/footer checksum calculation and verification.Motivation: with both options enabled, debug mode still records allocation numbers, thread IDs, timestamps and the allocation/free stack traces - everything needed for allocation profiling and leak analysis via
FastMM_WalkBlocks- but at a fraction of the cost. In a quick benchmark (200kGetMem/FreeMempairs of 4000 bytes, debug mode, Delphi 13.1 Win64) the loop drops from ~110 ms to below theGetTickCountresolution, since the dominant cost is the fill/checksum work over the user area. The trade-offs are documented in the option comments: no use-after-free / uninitialized-memory detection without fill patterns, no corruption detection without checksums.Consistency under option changes: the features actually applied to each block are recorded per block in the previously reserved byte of
TFastMM_DebugBlockHeader(nowDebugFeatureFlags). Every verification site (free, realloc, freed-block reuse,FastMM_ScanDebugBlocksForCorruption,HandleInvalidFreeMemOrReallocMem) consults the block's own flags rather than the currently active options, so the options may be toggled while debug mode is active and blocks allocated under different settings coexist safely. Default behaviour (options not set) is byte-for-byte unchanged.Verified with Delphi 10 Seattle and 13.1 (Win32 + Win64), warning-free: reference behaviour intact, both options individually effective, option changes while debug mode is active, and
FastMM_ScanDebugBlocksForCorruptionover mixed blocks.🤖 Generated with Claude Code