把一套 2003 年的 MFC 工程迁到 VS2022 x86,第一轮 65 个模块里 62 个翻红。收口之后回头看,绝大多数错误是两类。
LNK2005 的两个经典来源
- 自制函数与 CRT 撞名:老代码自己实现了
strnlen,新 CRT 也有。解法不是删函数,而是条件编译隔离——老 CRT 版本才编译自制实现; - 类名与 MFC 内部同名:工程里的
CMemDC(双缓冲封装)与新版 MFC 内部CMemDC在两个 OBJ 里重复定义。改名为CSoftMemDC,一处引用链全局替换。
API 签名桶
跨模块的公共头改动会引发连锁编译错误,策略是先建「签名桶」:把所有对外函数签名列出来,桶内对齐、桶间不动,改一处过一片。最后清零后只剩 3 个纯缺件(历史上就不存在的模块),登记不再追。
可玩客户端必须整套 Release(/MD)
血泪定案:运行时库混链(部分 /MD 部分 /MT,或混入 Debug DLL)的客户端能启动、能渲染,但会在某个 Debug 断言处卡死或
0xC0000374 堆损坏。整套统一 Release(/MD),缺哪个 DLL 补哪个,不做局部混搭。