chore(comments): Test 仓注释英文化(R11)
把 81 个 .vp 文件的中文 # 注释与三引号文档串改写为简洁英文,每个连续注释块 <=2 行;运行时中文字符串字面量(testcheck.begin/print 等用户可见消息)保持原样。骨架比对 HEAD 与工作区 112 文件漂移 0,全量 77/77 顺序回归通过。
This commit is contained in:
1 parent
aa5a7e7250
commit
ee6461be46
81 files changed
+1231
-1925
No files matched your search
@@ -10,9 +10,8 @@ def main() -> CInt | CExport:
|
||||
w32.win32console.SetConsoleCP(65001)
|
||||
w32.win32console.SetConsoleOutputCP(65001)
|
||||
|
||||
# memhub 的 [MEMDBG] 悬空/重复 free 检测默认开启(_memdbg_enable=1)。
|
||||
# BuddyTest 含"故意双重 free,期望静默拒绝且状态不损坏"的负向用例,
|
||||
# 若保持开启会在第二次 free 处终止进程 → 在此关闭 debug 模式。
|
||||
# BuddyTest has a negative case that deliberately double-frees. With memhub's
|
||||
# [MEMDBG] checks on (_memdbg_enable=1) the second free aborts, so disable it.
|
||||
memhub._memdbg_enable = 0
|
||||
|
||||
return mbuddytest.mbuddy_main()
|
||||
+73
-74
@@ -11,7 +11,7 @@ import w32.win32sync
|
||||
import w32.win32base
|
||||
|
||||
|
||||
# 线程函数: 在共享 MBuddy 上执行 alloc/free (测试 spinlock 线程安全)
|
||||
# Thread body: alloc/free on a shared MBuddy to exercise the spinlock
|
||||
def _thread_alloc_free(param: t.CPtr) -> uint32:
|
||||
bd: memhub.MemBuddy* = (memhub.MemBuddy*)(param)
|
||||
i: CInt
|
||||
@@ -29,7 +29,7 @@ def mbuddy_main() -> CInt:
|
||||
|
||||
testcheck.begin("BuddyTest: 伙伴系统内存分配器测试")
|
||||
|
||||
# === 基础 alloc/free 测试 ===
|
||||
# === Basic alloc/free ===
|
||||
testcheck.section("基础 alloc/free")
|
||||
arena: bytes = stdlib.malloc(65536)
|
||||
bd: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena, 65536)
|
||||
@@ -43,7 +43,7 @@ def mbuddy_main() -> CInt:
|
||||
testcheck.check(p1 != None and p2 != None and p3 != None,
|
||||
"3 allocs OK", "alloc FAILED")
|
||||
|
||||
# 写入数据验证指针可用
|
||||
# Write data to verify the returned pointer is usable
|
||||
p_c: CUInt8T | CPtr = CPtr(p1)
|
||||
p_c[0] = CUInt8T(0xAB)
|
||||
p_c[1] = CUInt8T(0xCD)
|
||||
@@ -57,19 +57,19 @@ def mbuddy_main() -> CInt:
|
||||
bd.free(p3)
|
||||
testcheck.ok("3 frees OK")
|
||||
|
||||
# 释放后验证合并: free_count 应回到初始分解块数 (10)
|
||||
# 4096-264 内非 2 的幂: 65536-264=65272 二进制分解为 10 个 2 的幂块
|
||||
# After free, coalescing must restore the initial 10 free blocks
|
||||
# (65536 - 264 = 65272 decomposes into 10 power-of-two blocks)
|
||||
testcheck.check(bd.free_count() == 10,
|
||||
"coalesce: free_count=10 OK", "coalesce: free_count != 10")
|
||||
|
||||
# 合并后应能分配大块
|
||||
# Coalesced space must allow a large alloc again
|
||||
big: bytes = bd.alloc(16000)
|
||||
testcheck.check(big != None, "big alloc OK", "big alloc FAILED")
|
||||
bd.free(big)
|
||||
|
||||
stdlib.free(arena)
|
||||
|
||||
# === calloc 测试 (验证清零) ===
|
||||
# === calloc (verify zeroing) ===
|
||||
testcheck.section("calloc 清零")
|
||||
arena2: bytes = stdlib.malloc(4096)
|
||||
viperlib.snprintf(buf, 256, "arena2 = %p", arena2)
|
||||
@@ -103,7 +103,7 @@ def mbuddy_main() -> CInt:
|
||||
|
||||
stdlib.free(arena2)
|
||||
|
||||
# === realloc 扩展测试 ===
|
||||
# === realloc grow ===
|
||||
testcheck.section("realloc 扩展")
|
||||
arena3: bytes = stdlib.malloc(4096)
|
||||
bd3: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena3, 4096)
|
||||
@@ -130,7 +130,7 @@ def mbuddy_main() -> CInt:
|
||||
|
||||
stdlib.free(arena3)
|
||||
|
||||
# === 原地收缩测试 (验证无泄漏) ===
|
||||
# === in-place shrink (verify no leak) ===
|
||||
testcheck.section("原地收缩 (realloc shrink)")
|
||||
arena_shrink: bytes = stdlib.malloc(4096)
|
||||
bds: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena_shrink, 4096)
|
||||
@@ -139,15 +139,15 @@ def mbuddy_main() -> CInt:
|
||||
testcheck.check(sp != None, "alloc 256 OK", "alloc 256 FAILED")
|
||||
|
||||
fc_before: CSizeT = bds.free_count()
|
||||
# realloc 到更小尺寸: 256+8=264 -> order 4 (512); 32+8=40 -> order 1 (64)
|
||||
# new_order(1) <= old_order(4), 应原地返回同一指针
|
||||
# Shrink 256 -> 32: order 4 (264) to order 1 (40); since new order <= old,
|
||||
# realloc must return the same pointer in place
|
||||
sp2: bytes = bds.realloc(sp, 32)
|
||||
fc_after: CSizeT = bds.free_count()
|
||||
|
||||
testcheck.check(sp2 == sp, "shrink same ptr OK", "shrink ptr changed")
|
||||
testcheck.check(fc_after == fc_before, "shrink no leak OK", "shrink LEAKED blocks")
|
||||
|
||||
# 验证数据仍可读写
|
||||
# Data must remain readable/writable after shrink
|
||||
sp_c: CUInt8T | CPtr = CPtr(sp2)
|
||||
sp_c[0] = CUInt8T(0x42)
|
||||
testcheck.check(sp_c[0] == CUInt8T(0x42), "shrink data OK", "shrink data FAILED")
|
||||
@@ -157,32 +157,32 @@ def mbuddy_main() -> CInt:
|
||||
|
||||
stdlib.free(arena_shrink)
|
||||
|
||||
# === 边界情况测试 ===
|
||||
# === Edge cases ===
|
||||
testcheck.section("边界情况")
|
||||
arena4: bytes = stdlib.malloc(4096)
|
||||
bd4: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena4, 4096)
|
||||
|
||||
# alloc(0) 应返回 None
|
||||
# alloc(0) must return None
|
||||
z: bytes = bd4.alloc(0)
|
||||
testcheck.check(z == None, "alloc(0)=None OK", "alloc(0) should be None")
|
||||
|
||||
# free(None) 应安全
|
||||
# free(None) must be safe
|
||||
bd4.free(None)
|
||||
testcheck.ok("free(None) safe")
|
||||
|
||||
# realloc(None, size) 等价于 alloc
|
||||
# realloc(None, size) behaves like alloc
|
||||
rn: bytes = bd4.realloc(None, 32)
|
||||
testcheck.check(rn != None, "realloc(None)=alloc OK", "realloc(None) FAILED")
|
||||
bd4.free(rn)
|
||||
|
||||
# realloc(ptr, 0) 等价于 free
|
||||
# realloc(ptr, 0) behaves like free
|
||||
rz: bytes = bd4.alloc(32)
|
||||
rz2: bytes = bd4.realloc(rz, 0)
|
||||
testcheck.check(rz2 == None, "realloc(ptr,0)=free OK", "realloc(ptr,0) should be None")
|
||||
|
||||
stdlib.free(arena4)
|
||||
|
||||
# === 非法指针防护测试 ===
|
||||
# === Illegal pointer defense ===
|
||||
testcheck.section("非法指针防护")
|
||||
arena5: bytes = stdlib.malloc(4096)
|
||||
bd5: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena5, 4096)
|
||||
@@ -190,7 +190,7 @@ def mbuddy_main() -> CInt:
|
||||
valid: bytes = bd5.alloc(32)
|
||||
testcheck.check(valid != None, "alloc for illegal test OK", "alloc FAILED")
|
||||
|
||||
# 1. free 随机地址 (地址 1)
|
||||
# 1. free a random address (address 1)
|
||||
bd5.free(t.CPtr(uint64(1)))
|
||||
testcheck.ok("free(addr=1) ignored")
|
||||
|
||||
@@ -198,39 +198,39 @@ def mbuddy_main() -> CInt:
|
||||
bd5.free(None)
|
||||
testcheck.ok("free(NULL) ignored")
|
||||
|
||||
# 3. free 越界指针 (arena 之前)
|
||||
# 3. free an out-of-range pointer (before arena)
|
||||
bd5.free(t.CPtr(uint64(arena5)))
|
||||
testcheck.ok("free(before arena) ignored")
|
||||
|
||||
# 4. free 越界指针 (arena 之后)
|
||||
# 4. free an out-of-range pointer (after arena)
|
||||
bd5.free(t.CPtr(uint64(arena5) + 99999))
|
||||
testcheck.ok("free(after arena) ignored")
|
||||
|
||||
# 5. free 未对齐指针 (arena + 1, 在 mem 区域内但不对齐)
|
||||
# 5. free a misaligned pointer (inside mem but not aligned)
|
||||
bd5.free(t.CPtr(uint64(bd5.base) + 1))
|
||||
testcheck.ok("free(misaligned) ignored")
|
||||
|
||||
# 6. 验证合法 free 仍正常工作 (释放后应能再次分配)
|
||||
# 6. a valid free must still work (block reusable after)
|
||||
bd5.free(valid)
|
||||
retry5: bytes = bd5.alloc(32)
|
||||
testcheck.check(retry5 != None, "valid free still works OK", "valid free BROKEN")
|
||||
if retry5 != None:
|
||||
bd5.free(retry5)
|
||||
|
||||
# 7. realloc 非法指针应返回 None
|
||||
# 7. realloc on an illegal pointer must return None
|
||||
r_illegal: bytes = bd5.realloc(t.CPtr(1), 64)
|
||||
testcheck.check(r_illegal == None, "realloc(illegal)=None OK", "realloc(illegal) should be None")
|
||||
|
||||
stdlib.free(arena5)
|
||||
|
||||
# === OOM 内存耗尽测试 ===
|
||||
# === OOM exhaustion ===
|
||||
testcheck.section("OOM 内存耗尽")
|
||||
arena6: bytes = stdlib.malloc(4096)
|
||||
bd6: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena6, 4096)
|
||||
|
||||
# 持续分配直到失败
|
||||
# Allocate until failure
|
||||
alloc_count: CInt = 0
|
||||
ptrs_arr: bytes = stdlib.malloc(8 * 256) # 存储指针的数组
|
||||
ptrs_arr: bytes = stdlib.malloc(8 * 256) # Pointer storage array
|
||||
ptrs: CUInt64T | CPtr = CPtr(ptrs_arr)
|
||||
|
||||
while alloc_count < 256:
|
||||
@@ -244,11 +244,11 @@ def mbuddy_main() -> CInt:
|
||||
testcheck.info(buf)
|
||||
testcheck.check(alloc_count > 0, "OOM: got some allocs OK", "OOM: no allocs at all")
|
||||
|
||||
# 尝试再分配应失败
|
||||
# Another alloc must now fail
|
||||
oom_p: bytes = bd6.alloc(32)
|
||||
testcheck.check(oom_p == None, "OOM: alloc fails OK", "OOM: alloc should fail")
|
||||
|
||||
# 释放一个块后应能再次分配
|
||||
# After freeing one block, allocation must succeed again
|
||||
if alloc_count > 0:
|
||||
first_ptr: bytes = t.CPtr(ptrs[0])
|
||||
bd6.free(first_ptr)
|
||||
@@ -257,51 +257,51 @@ def mbuddy_main() -> CInt:
|
||||
if retry != None:
|
||||
bd6.free(retry)
|
||||
|
||||
# 释放所有块
|
||||
# Free all blocks
|
||||
for idx in range(1, alloc_count):
|
||||
cur_p: bytes = t.CPtr(ptrs[idx])
|
||||
bd6.free(cur_p)
|
||||
|
||||
# 全部释放后应能合并回初始分解块数 (6)
|
||||
# Full free must coalesce back to the initial 6 blocks
|
||||
testcheck.check(bd6.free_count() == 6,
|
||||
"OOM: full coalesce OK", "OOM: free_count != 6 after full free")
|
||||
|
||||
stdlib.free(ptrs_arr)
|
||||
stdlib.free(arena6)
|
||||
|
||||
# === 空闲链表状态测试 ===
|
||||
# === Free-list state ===
|
||||
testcheck.section("空闲链表状态")
|
||||
arena7: bytes = stdlib.malloc(4096)
|
||||
bd7: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena7, 4096)
|
||||
|
||||
# 初始: 非 2 的幂 arena (4096-264=3832) 二进制分解为 6 个块
|
||||
# Initial: non-power-of-two arena (4096 - 264 = 3832) splits into 6 blocks
|
||||
testcheck.check(bd7.free_count() == 6, "init: 6 free blocks OK", "init: free_count != 6")
|
||||
|
||||
# 分配后: 空闲块数应增加 (分裂产生多个小块)
|
||||
# After alloc: free count grows because a block is split
|
||||
a1: bytes = bd7.alloc(32)
|
||||
fc1: CSizeT = bd7.free_count()
|
||||
viperlib.snprintf(buf, 256, "after alloc(32): free_count=%lu", fc1)
|
||||
testcheck.info(buf)
|
||||
testcheck.check(fc1 > 1, "after alloc: split OK", "after alloc: no split")
|
||||
|
||||
# 再分配
|
||||
# Second alloc
|
||||
a2: bytes = bd7.alloc(32)
|
||||
fc2: CSizeT = bd7.free_count()
|
||||
testcheck.check(fc2 >= 1, "after 2nd alloc: free >= 1 OK", "after 2nd alloc: free < 1")
|
||||
|
||||
# 释放 a1: 空闲块数应增加
|
||||
# Free a1: free count must increase
|
||||
bd7.free(a1)
|
||||
fc3: CSizeT = bd7.free_count()
|
||||
testcheck.check(fc3 > fc2, "after free a1: free increased OK", "after free a1: free not increased")
|
||||
|
||||
# 释放 a2: 应合并, 空闲块数回到初始 6 块
|
||||
# Free a2: coalescing must restore the initial 6 blocks
|
||||
bd7.free(a2)
|
||||
testcheck.check(bd7.free_count() == 6,
|
||||
"after free all: coalesced to 6 OK", "after free all: free_count != 6")
|
||||
|
||||
stdlib.free(arena7)
|
||||
|
||||
# === with 上下文管理器测试 ===
|
||||
# === with context manager ===
|
||||
testcheck.section("with 上下文管理器")
|
||||
arena8: bytes = stdlib.malloc(4096)
|
||||
with memhub.MemBuddy(arena8, 4096) as wbd:
|
||||
@@ -309,16 +309,16 @@ def mbuddy_main() -> CInt:
|
||||
wp2: bytes = wbd.alloc(64)
|
||||
testcheck.check(wp1 != None and wp2 != None,
|
||||
"with: allocs OK", "with: allocs FAILED")
|
||||
# 退出 with 块时 __exit__ 自动 reset
|
||||
# Leaving the with block triggers __exit__ auto-reset
|
||||
|
||||
# 退出后重新进入,验证 reset 生效
|
||||
# Re-enter after exit to verify the reset took effect
|
||||
with memhub.MemBuddy(arena8, 4096) as wbd2:
|
||||
wp3: bytes = wbd2.alloc(1024)
|
||||
testcheck.check(wp3 != None, "with: reset+realloc OK", "with: reset+realloc FAILED")
|
||||
|
||||
stdlib.free(arena8)
|
||||
|
||||
# === 双重 free 检测测试 ===
|
||||
# === Double-free detection ===
|
||||
testcheck.section("双重 free 检测")
|
||||
arena_df: bytes = stdlib.malloc(4096)
|
||||
bd_df: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena_df, 4096)
|
||||
@@ -326,17 +326,17 @@ def mbuddy_main() -> CInt:
|
||||
df: bytes = bd_df.alloc(64)
|
||||
testcheck.check(df != None, "df: alloc OK", "df: alloc FAILED")
|
||||
|
||||
# 第一次 free
|
||||
# First free
|
||||
bd_df.free(df)
|
||||
fc_df1: CSizeT = bd_df.free_count()
|
||||
testcheck.ok("first free OK")
|
||||
|
||||
# 第二次 free (双重 free) — 应被静默拒绝
|
||||
# Second free (double free): must be silently rejected
|
||||
bd_df.free(df)
|
||||
fc_df2: CSizeT = bd_df.free_count()
|
||||
testcheck.check(fc_df2 == fc_df1, "double free rejected OK", "double free CORRUPTED state")
|
||||
|
||||
# 验证分配器仍正常工作
|
||||
# Allocator must still be functional
|
||||
df2: bytes = bd_df.alloc(64)
|
||||
testcheck.check(df2 != None, "df: alloc after double-free OK", "df: alloc after double-free FAILED")
|
||||
if df2 != None:
|
||||
@@ -344,36 +344,36 @@ def mbuddy_main() -> CInt:
|
||||
|
||||
stdlib.free(arena_df)
|
||||
|
||||
# === 自检功能测试 ===
|
||||
# === Self-check ===
|
||||
testcheck.section("自检功能")
|
||||
arena_sc: bytes = stdlib.malloc(4096)
|
||||
bd_sc: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena_sc, 4096)
|
||||
|
||||
# 初始状态自检
|
||||
# Self-check on initial state
|
||||
testcheck.check(bd_sc.self_check() == 0, "self_check init OK", "self_check init FAILED")
|
||||
|
||||
# 分配后自检
|
||||
# Self-check after alloc
|
||||
sc_p1: bytes = bd_sc.alloc(32)
|
||||
sc_p2: bytes = bd_sc.alloc(128)
|
||||
testcheck.check(bd_sc.self_check() == 0, "self_check after alloc OK", "self_check after alloc FAILED")
|
||||
|
||||
# 部分释放后自检
|
||||
# Self-check after partial free
|
||||
bd_sc.free(sc_p1)
|
||||
testcheck.check(bd_sc.self_check() == 0, "self_check after partial free OK", "self_check after partial free FAILED")
|
||||
|
||||
# 全部释放后自检 (应合并回单个大块)
|
||||
# Self-check after full free (should coalesce to one block)
|
||||
bd_sc.free(sc_p2)
|
||||
testcheck.check(bd_sc.self_check() == 0, "self_check after full free OK", "self_check after full free FAILED")
|
||||
|
||||
# 双重 free 后自检 (验证状态未损坏)
|
||||
# Self-check after double free (state must be intact)
|
||||
sc_p3: bytes = bd_sc.alloc(64)
|
||||
bd_sc.free(sc_p3)
|
||||
bd_sc.free(sc_p3) # 双重 free,应被拒绝
|
||||
bd_sc.free(sc_p3) # Double free, must be rejected
|
||||
testcheck.check(bd_sc.self_check() == 0, "self_check after double-free OK", "self_check after double-free CORRUPTED")
|
||||
|
||||
stdlib.free(arena_sc)
|
||||
|
||||
# === 并发多线程测试 (spinlock) ===
|
||||
# === Concurrent threads (spinlock) ===
|
||||
testcheck.section("并发多线程 (spinlock)")
|
||||
arena_mt: bytes = stdlib.malloc(65536)
|
||||
bd_mt: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena_mt, 65536)
|
||||
@@ -383,19 +383,19 @@ def mbuddy_main() -> CInt:
|
||||
handles: CUInt64T | CPtr = CPtr(handles_arr)
|
||||
tid: CUInt32T = 0
|
||||
|
||||
# 创建 4 个线程并发 alloc/free
|
||||
# Spawn 4 threads doing concurrent alloc/free
|
||||
t_idx: CInt
|
||||
for t_idx in range(NUM_THREADS):
|
||||
h: bytes = w32.win32process.CreateThread(None, 0, _thread_alloc_free, t.CPtr(bd_mt), 0, &tid)
|
||||
handles[t_idx] = CUInt64T(h)
|
||||
|
||||
# 等待所有线程完成
|
||||
# Wait for all threads to finish
|
||||
for t_idx in range(NUM_THREADS):
|
||||
h: bytes = t.CPtr(handles[t_idx])
|
||||
w32.win32sync.WaitForSingleObject(h, w32.win32base.INFINITE)
|
||||
w32.win32base.CloseHandle(h)
|
||||
|
||||
# 验证分配器状态: 自检通过,所有块已合并
|
||||
# Verify allocator state: self-check passes and all blocks coalesced
|
||||
testcheck.check(bd_mt.self_check() == 0, "mt: self_check OK", "mt: self_check FAILED")
|
||||
testcheck.check(bd_mt.free_count() == 10, "mt: free_count=10 OK", "mt: free_count != 10 (leaked)")
|
||||
|
||||
@@ -405,18 +405,18 @@ def mbuddy_main() -> CInt:
|
||||
stdlib.free(handles_arr)
|
||||
stdlib.free(arena_mt)
|
||||
|
||||
# === 极端边界测试 ===
|
||||
# === Extreme boundaries ===
|
||||
testcheck.section("极端边界")
|
||||
|
||||
# 1. 分配尺寸恰巧是块边界
|
||||
# 1. Alloc size exactly at a block boundary
|
||||
arena_ex: bytes = stdlib.malloc(4096)
|
||||
bd_ex: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena_ex, 4096)
|
||||
|
||||
# 24 + 16 = 40 > 32(8 头 + 8 哨兵),需要 order 1 (64 字节)
|
||||
# 24 + 16 = 40 > 32 (8 header + 8 sentinel), needs order 1 (64 bytes)
|
||||
exact_fit: bytes = bd_ex.alloc(24)
|
||||
testcheck.check(exact_fit != None, "exact fit order 0 OK", "exact fit order 0 FAILED")
|
||||
|
||||
# 25 + 16 = 41 > 32, 需要 order 1 (64 字节)
|
||||
# 25 + 16 = 41 > 32, needs order 1 (64 bytes)
|
||||
over_fit: bytes = bd_ex.alloc(25)
|
||||
testcheck.check(over_fit != None, "over by 1 byte OK", "over by 1 byte FAILED")
|
||||
|
||||
@@ -424,14 +424,13 @@ def mbuddy_main() -> CInt:
|
||||
bd_ex.free(over_fit)
|
||||
testcheck.check(bd_ex.free_count() == 6, "boundary: coalesce OK", "boundary: coalesce FAILED")
|
||||
|
||||
# 2. 单次分配接近最大块上限(order6=2048,非 2 的幂 arena 的最大分解块)
|
||||
# 可用数据区 = 2048 - 8(头) - 8(哨兵),alloc(max_usable) 的 needed 恰好
|
||||
# = 2048,正好填满 order6 最大块
|
||||
# 2. Alloc near the largest block limit (order6 = 2048): usable = 2048 - 16,
|
||||
# so alloc(max_usable) exactly fills one order6 block
|
||||
max_usable: CSizeT = 2048 - 16
|
||||
viperlib.snprintf(buf, 256, "mem_size=%lu, max_block=2048, max_usable=%lu", bd_ex.mem_size, max_usable)
|
||||
testcheck.info(buf)
|
||||
|
||||
# 恰好用完 order6 块(其余 5 个分解块空闲)
|
||||
# Exactly consumes the order6 block (5 other blocks stay free)
|
||||
exact_max: bytes = bd_ex.alloc(max_usable)
|
||||
testcheck.check(exact_max != None, "exact max alloc OK", "exact max alloc FAILED")
|
||||
testcheck.check(bd_ex.free_count() == 5, "max alloc: 5 free blocks left OK", "max alloc: free_count != 5")
|
||||
@@ -439,12 +438,12 @@ def mbuddy_main() -> CInt:
|
||||
bd_ex.free(exact_max)
|
||||
testcheck.check(bd_ex.free_count() == 6, "max free: coalesce OK", "max free: coalesce FAILED")
|
||||
|
||||
# 再次分配同样大小 — 验证合并后可再次使用
|
||||
# Alloc the same size again to verify coalesced space is reusable
|
||||
exact_max2: bytes = bd_ex.alloc(max_usable)
|
||||
testcheck.check(exact_max2 != None, "exact max re-alloc OK", "exact max re-alloc FAILED")
|
||||
bd_ex.free(exact_max2)
|
||||
|
||||
# 3. 分配超过 arena 上限 — 应失败
|
||||
# 3. Alloc beyond the arena limit must fail
|
||||
over_max: bytes = bd_ex.alloc(bd_ex.mem_size)
|
||||
testcheck.check(over_max == None, "over max: fails OK", "over max: should fail")
|
||||
|
||||
@@ -453,7 +452,7 @@ def mbuddy_main() -> CInt:
|
||||
|
||||
stdlib.free(arena_ex)
|
||||
|
||||
# 4. Arena 太小 (仅够 free_lists 开销, 264 字节)
|
||||
# 4. Arena too small (only fits the 264-byte free-list overhead)
|
||||
arena_tiny: bytes = stdlib.malloc(264)
|
||||
bd_tiny: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena_tiny, 264)
|
||||
testcheck.check(bd_tiny.stats() == 0, "tiny arena: stats=0 OK", "tiny arena: stats != 0")
|
||||
@@ -461,12 +460,12 @@ def mbuddy_main() -> CInt:
|
||||
testcheck.check(tiny_p == None, "tiny arena: alloc fails OK", "tiny arena: should fail")
|
||||
stdlib.free(arena_tiny)
|
||||
|
||||
# 5. Arena 刚好够一个最小块 (264 + 32 = 296)
|
||||
# 5. Arena fits exactly one minimal block (264 + 32 = 296)
|
||||
arena_one: bytes = stdlib.malloc(296)
|
||||
bd_one: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena_one, 296)
|
||||
testcheck.check(bd_one.stats() == 32, "one block: stats=32 OK", "one block: stats != 32")
|
||||
|
||||
# 最小块 32 字节 = 数据 16 + 头 8 + 哨兵 8,alloc(16) 恰好填满
|
||||
# Minimal block 32 = data 16 + header 8 + sentinel 8; alloc(16) fills it
|
||||
one_p: bytes = bd_one.alloc(16)
|
||||
testcheck.check(one_p != None, "one block: alloc OK", "one block: alloc FAILED")
|
||||
|
||||
@@ -477,20 +476,20 @@ def mbuddy_main() -> CInt:
|
||||
testcheck.check(bd_one.free_count() == 1, "one block: free OK", "one block: free FAILED")
|
||||
stdlib.free(arena_one)
|
||||
|
||||
# 6. 2 的幂 arena vs 非 2 的幂 arena
|
||||
# 6. Power-of-two vs non-power-of-two arena
|
||||
arena_pow2: bytes = stdlib.malloc(512)
|
||||
bd_pow2: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena_pow2, 512)
|
||||
# 512 - 264 = 248, 二进制分解 = 128+64+32 = 224 (尾 24 字节碎片不入池)
|
||||
# 512 - 264 = 248, decomposes to 128 + 64 + 32 = 224 (24-byte tail dropped)
|
||||
testcheck.check(bd_pow2.stats() == 224, "pow2 arena: stats=224 OK", "pow2 arena: stats != 224")
|
||||
stdlib.free(arena_pow2)
|
||||
|
||||
arena_non2: bytes = stdlib.malloc(500)
|
||||
bd_non2: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena_non2, 500)
|
||||
# 500 - 264 = 236, 二进制分解 = 128+64+32 = 224 (尾 12 字节碎片不入池)
|
||||
# 500 - 264 = 236, decomposes to 128 + 64 + 32 = 224 (12-byte tail dropped)
|
||||
testcheck.check(bd_non2.stats() == 224, "non-pow2 arena: stats=224 OK", "non-pow2 arena: stats != 224")
|
||||
stdlib.free(arena_non2)
|
||||
|
||||
# 7. 压力测试: 反复 alloc/free 同一尺寸 1000 次
|
||||
# 7. Stress: 1000 alloc/free cycles of the same size
|
||||
arena_stress: bytes = stdlib.malloc(4096)
|
||||
bd_stress: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena_stress, 4096)
|
||||
|
||||
@@ -506,7 +505,7 @@ def mbuddy_main() -> CInt:
|
||||
testcheck.check(bd_stress.free_count() == 6, "stress: free_count=6 OK", "stress: leaked")
|
||||
stdlib.free(arena_stress)
|
||||
|
||||
# 8. 分配全部最小块然后全部释放
|
||||
# 8. Allocate all minimal blocks, then free them all
|
||||
arena_fill: bytes = stdlib.malloc(4096)
|
||||
bd_fill: memhub.MemBuddy | CPtr = memhub.MemBuddy(arena_fill, 4096)
|
||||
|
||||
@@ -527,7 +526,7 @@ def mbuddy_main() -> CInt:
|
||||
testcheck.check(fill_count > 0, "fill: got blocks OK", "fill: no blocks")
|
||||
testcheck.check(bd_fill.self_check() == 0, "fill: self_check OK", "fill: self_check FAILED")
|
||||
|
||||
# 全部释放
|
||||
# Free all
|
||||
fi: CInt
|
||||
for fi in range(fill_count):
|
||||
fp2: bytes = t.CPtr(fill_ptrs[fi])
|
||||
|
||||
Reference in new issue
Block a user