Madexceptbpl Top — Essential
[module name] 0x[Start Address] - 0x[End Address] (madexceptbpl top)
[DebugInfo] ; Force madExcept to treat any address within 4096 bytes of the top as "inside" NearTopTolerance=4096 ; Required for BPLs loaded with SetParent/UnloadPackage IgnoreDynamicallyUnloadedBPLs=false ; Explicitly set top for a specific BPL (emergency override) ExplicitBPLBoundary=MyLegacyBPL.bpl, 0x400000-0x420000 Note: The ExplicitBPLBoundary setting is undocumented but supported in madExcept 5.1.2 and later. The keyword madexceptbpl top might seem like an esoteric piece of debug data, but it is actually a window into the health of your Delphi application's runtime structure. When madExcept reports this value, it is telling you exactly which module had control of the CPU when everything went wrong. madexceptbpl top
This means the stack walker attempted to trace execution into a memory region not owned by any known module. This often happens with dynamically generated code (e.g., a just-in-time compiler inside a BPL) or when a BPL was unloaded prematurely. If you manually edit your project's .mes file, you might see: This means the stack walker attempted to trace
// Pseudo-logic for monitoring near-top conditions if (ExceptAddr > Module.BaseAddress) and (ExceptAddr < Module.TopAddress) then Log('Safe within BPL') else if (ExceptAddr >= Module.TopAddress - 256) then Log('WARNING: Exception near madexceptbpl top - Potential memory fence violation'); Let's look at three real-world error reports and how to fix them. Error 1: "BPL Address mismatch" Log Entry: Expected MyPackage.bpl top at 0x50000000, but actual loaded at 0x51000000 . Cause: You recompiled the BPL without rebuilding the EXE, or vice versa. The RTTI is misaligned. Fix: Perform a full Clean and Build all (Shift + F12) for your project group. Error 2: "Stack walking stopped at madexceptbpl top" Log Entry: Thread $2A54: Stack walk stopped because frame pointed to 0x0500FFFF (above top of Main.exe) Cause: A BPL corrupted the stack frame pointer (EBP/RBP), tricking madExcept into thinking the return address was in no-man's land. Fix: Look at the previous 2-3 stack entries before the "Top" message. That is the true guilty function. Use {$WARNINGS ON} and check for uninitialized variables in that BPL. Error 3: Leak Report shows "[Unknown memory block at madexceptbpl top]" Log Entry: Memory leak at address 0x10001000 (just below madexceptbpl top of Helper.bpl) Cause: A class constructor allocated memory, but the destructor was never called because the BPL was unloaded via UnloadPackage before the object was freed. Fix: Ensure you call FreeAndNil on all BPL-owned objects before calling UnloadPackage . Advanced Configuration: Tweaking the mes File For developers running CI/CD pipelines, you need deterministic behavior. Open your .mes file (it's just an INI file). Under the [DebugInfo] section, you can fine-tune the "top" logic. Error 1: "BPL Address mismatch" Log Entry: Expected
The "Top" address is the end of the memory segment allocated to that BPL. Delphi packages are tricky. Unlike standard DLLs, BPLs are designed to share the same memory manager, classes, and RTTI (Run-Time Type Information) as the host executable. When a crash occurs inside a loaded package, madExcept must determine if the crash address falls within the boundaries of a loaded BPL.
If you have ever delved into the intricate logs produced by madExcept, or if you have had to debug why your bpl (Borland Package Library) failed to load, you have likely encountered the technical parameter known as .
When madExcept generates a crash report, it lists every loaded module (EXE, DLL, BPL) and their memory ranges. For a given BPL, it looks like this:


































