diff --git a/App/lib/core/Gen/StructGenMixin.vp b/App/lib/core/Gen/StructGenMixin.vp index 5636eaf..5382a37 100644 --- a/App/lib/core/Gen/StructGenMixin.vp +++ b/App/lib/core/Gen/StructGenMixin.vp @@ -153,8 +153,18 @@ novirtual class StructGenMixin: pool: 内存分配器(严格模式下创建 HashTable) strict: 1=严格模式(用户文件),0=宽松模式(includes 文件) + + `ModuleClasses` 也在此**每文件重建**:它的键是 pool 字符串,而 pool 在 + 文件/遍切换时会被 reset ⇒ 若表跨文件长期存活,`_find_slot` 会 strcmp 到 + 已回收的键(现场:ASan access-violation,rcx=0x1,栈 + mark_module_class → HashTable.set_int → _resize → _find_slot → strcmp)。 + 与 `VisibleStructs` 同口径(同样每文件新建、键同池),故无悬空。 + `CurDefModuleSha1` 指向 `trans.ModuleSha1`(同一 pool 的串),同样必须 + 每文件清空,否则下一次 strcat/strcmp 读的是已回收内存。 """ self.StrictVisibility = strict + self.CurDefModuleSha1 = None + self.ModuleClasses = hashtable.HashTable(pool) if strict != 0: # 严格模式:创建新的 HashTable 记录可见结构体 self.VisibleStructs = hashtable.HashTable(pool) @@ -195,18 +205,22 @@ novirtual class StructGenMixin: def mark_module_class(self, pool: memhub.MemBuddy*, sha1: str, name: str) -> None: """登记"{sha1}.{类名}":**该模块声明了这个类**(类定义入口调用一次)。 - 键里带 SHA1 ⇒ 天然按"声明模块"区分,且与翻译顺序/模块切换无关(不需要 - 每文件重置):即使表里残留别的模块的登记,查询方只会命中 - (它自己那一对 sha1+类名),不会把别的模块的类错认成自己的。 + 键里带 SHA1 ⇒ 天然按"声明模块"区分。表由 `reset_visible_structs` **每文件 + 重建**(与键同池 ⇒ 无悬空),因此这里的登记只在本文件本遍内有效 —— + 恰好覆盖使用者(`_norm_type_arg_name` 规则 5.5)的窗口:判"类定义中"的 + 自引用字段时,登记与查询在同一文件同一遍内。 + + `CurDefModuleSha1` 同步记录("正在定义类所属模块"的权威来源,任何翻译 + 路径上都是 trans.ModuleSha1)。 """ - if pool is None or sha1 is None or name is None: + if sha1 is None or name is None: return - # 同步记录"正在定义类所属模块"(任何翻译路径上唯一的权威来源) self.CurDefModuleSha1 = sha1 - if self.ModuleClasses is None: - self.ModuleClasses = hashtable.HashTable(pool) - if self.ModuleClasses is None: - return + if pool is None or self.ModuleClasses is None: + # 未按文件初始化(该路径未调用 reset_visible_structs):不登记。 + # 不在此懒建表 —— 表必须与键同池、且随文件重置,否则会 strcmp 到 + # 已回收的键(ASan access-violation 现场)。 + return k_buf: str = self._module_class_key(pool, sha1, name) if k_buf is None: return