我正在编写一个在Windows上运行的链接器,并且我已经接受了PE格式目标文件的大多数功能,但是我遇到了_aenvptr和_wenvptr的重复定义的问题在libcmt。
从我能够在PE文档,Microsoft编译器和dumpbin的试错之间以及偶尔的问题之间弄清楚,规则是:
int x;
作为全局变量转换为没有部分的IMAGE_SYM_CLASS_EXTERNAL。如果这发生在多个目标文件中,这很好,最大的一个被用作BSS定义。
int x = 0;
作为全局变量转换为带有BSS部分的IMAGE_SYM_CLASS_EXTERNAL。如果这发生在多个目标文件中,则这是重复的符号错误。
问题是libcmt在后一种形式中提供了_aenvptr和_wenvptr的多个定义。微软的链接器对此感到满意,但是对于我所创建的小型测试库中的等效案例,它并不满意。
_aenvptr和_wenvptr不是COMDAT,它们也没有任何辅助符号记录或我能找到的任何其他奇怪的东西。
我错过了什么?
答案 0 :(得分:1)
这些符号在两个对象中定义,是:crt0.obj和dllcrt0.obj中都有定义。这些对象分别包含EXE和DLL的启动代码。
这里的诀窍是绝不应该将两个对象链接到单个模块中。链接器不会将库中的所有对象都拉到链接中;相反,它只会提取满足依赖关系所需的任何对象。没有crt0.obj和dllcrt0.obj都链接到单个模块的情况;它们的使用是相互排斥的。
基本上,库中可以存在许多相同外部符号的定义,只要[1]每个定义在不同的对象中,[2]实际上只在链接中使用其中一个对象。