diff --git a/Test/BuddyTest/App/main.vp b/Test/BuddyTest/App/main.vp index 83c21b0..fd9c7aa 100644 --- a/Test/BuddyTest/App/main.vp +++ b/Test/BuddyTest/App/main.vp @@ -2,6 +2,7 @@ from stdint import * import w32.win32console import t, c from t import CInt, CExport +import memhub import mbuddytest @@ -9,4 +10,9 @@ def main() -> CInt | CExport: w32.win32console.SetConsoleCP(65001) w32.win32console.SetConsoleOutputCP(65001) + # memhub 的 [MEMDBG] 悬空/重复 free 检测默认开启(_memdbg_enable=1)。 + # BuddyTest 含"故意双重 free,期望静默拒绝且状态不损坏"的负向用例, + # 若保持开启会在第二次 free 处终止进程 → 在此关闭 debug 模式。 + memhub._memdbg_enable = 0 + return mbuddytest.mbuddy_main() diff --git a/includes/memhub.vp b/includes/memhub.vp index 59b79b8..1843d74 100644 --- a/includes/memhub.vp +++ b/includes/memhub.vp @@ -60,6 +60,12 @@ MEMBUDDY_DET_PROBE_PERIOD: t.CDefine = 32 # 3. free :无效/悬空指针(池内但 header 偶数=已释放)不再静默忽略; # 4. 既有 [DET]/[MEM] 终止路径补 stdio.fflush(None)(stdout 重定向丢输出)。 MEMBUDDY_DBG: t.CDefine = 1 +# [MEMDBG] 运行时开关:默认开(随 MEMBUDDY_DBG 编译默认值)。 +# 需要让负向用例(如 BuddyTest 故意双重 free,期望"静默拒绝")不终止时, +# 可在运行期关闭(沿用 ast._mbuddy/sys._mbuddy 式跨模块全局写法): +# import memhub +# memhub._memdbg_enable = 0 +_memdbg_enable: int = MEMBUDDY_DBG def _canary_pattern() -> t.CUInt64T: @@ -715,7 +721,7 @@ class MemBuddy(MemManager): stdio.fflush(None) stdlib.exit(1) dup_i += 1 - if MEMBUDDY_DBG != 0: + if _memdbg_enable != 0: # [MEMDBG] 新出块是否仍残留于同 order free list(此前的重复 put # 使链表含两条本块 → pop 后还有残条 → 本块将被二次分配,双向写穿)。 # 记录表重叠检测要等下次 pop 同地址才撞见,这里在出块当场提前拦截。 @@ -811,7 +817,18 @@ class MemBuddy(MemManager): stored: t.CVoid | t.CPtr = t.CVoid(c.Deref(t.CUInt64T(block, t.CPtr)), t.CPtr) stored_val: t.CUInt64T = t.CUInt64T(stored) order: t.CInt = t.CInt(stored_val >> 1) - if MEMBUDDY_DBG != 0: + if (stored_val & 1) == 0: + # 双重 free:块已释放(header 偶)。debug 关 = 按原语义静默忽略 + # (不再次 coalesce,避免 free list 重复 put 污染);debug 开 = + # 终止并暴露悬空/重复 free 调用点。 + if _memdbg_enable != 0: + stdio.printf("[MEMDBG] 悬空/重复 free: ptr=%llu block=%llu header=0x%llX(偶数=已释放/未初始化,终止)\n", + t.CUInt64T(ptr), t.CUInt64T(block), stored_val) + stdio.fflush(None) + stdlib.exit(1) + self._unlock() + return 1 + if _memdbg_enable != 0: # [MEMDBG] 重复归还检测:活跃块(header 奇数)绝不该已在本 order # free list;命中 = 同块被 put 两次(free list 重复 put 实锤)。 dbg_f: t.CVoid | t.CPtr = t.CVoid(self.free_lists[order], t.CPtr) @@ -830,7 +847,7 @@ class MemBuddy(MemManager): dbg_f = t.CVoid(c.Deref(t.CUInt64T(dbg_f, t.CPtr)), t.CPtr) c.DerefAs(block, t.CVoid(0, t.CPtr)) self._coalesce(block, order) - elif MEMBUDDY_DBG != 0: + elif _memdbg_enable != 0: # [MEMDBG] 无效/悬空 free(原实现静默忽略):块在本池范围内但 header # 为偶 = 已被释放/未初始化 → 悬空重复 free(stale 指针)。范围外 # (非本池指针)是正常多池场景,不报。