Jav*_*Man 15 c++ compiler-construction linker visual-c++
编译器(MS Visual C++ 2010)如何在不同的cpp源文件中组合相同的字符串文字?例如,如果我分别在src1.cpp和src2.cpp中有字符串文字"hello world \n".编译的exe文件在constant/readonly部分中可能只有1个"hello world"字符串文字.这个任务是由链接器完成的吗?
我希望实现的是我得到了一些用汇编编写的模块供C++模块使用.这些汇编模块包含许多长字符串文字定义.我知道字符串文字与C++源代码中的其他字符串文字相同.如果我将我的程序集生成的obj代码与编译器生成的obj代码链接,那么这些字符串文字是否会被链接器合并以删除冗余字符串,就像所有模块都在C++中一样?
(注意以下内容仅适用于MSVC)
我的第一个答案是误导,因为我认为字面合并是链接器完成的魔术(并且/GF只有链接器才需要标记).
然而,这是一个错误.事实证明链接器在合并字符串文字方面几乎没有特别的参与 - 当发生/GF给编译器的选项时,它会将字符串文字放在目标文件的"COMDAT"部分中,其对象名称基于内容字符串文字.因此编译步骤/GF需要标志,而不是链接步骤.
使用该/GF选项时,编译器将每个字符串文字放在一个单独的部分中作为COMDAT对象放在目标文件中.具有相同名称的各种COMDAT对象将由链接器折叠(我不完全确定COMDAT的语义,或者如果具有相同名称的对象具有不同的数据,链接器可能会执行的操作).所以包含的C文件
char* another_string = "this is a string";
Run Code Online (Sandbox Code Playgroud)
将在目标文件中具有以下内容:
SECTION HEADER #3
.rdata name
0 physical address
0 virtual address
11 size of raw data
147 file pointer to raw data (00000147 to 00000157)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
40301040 flags
Initialized Data
COMDAT; sym= "`string'" (??_C@_0BB@LFDAHJNG@this?5is?5a?5string?$AA@)
4 byte align
Read Only
RAW DATA #3
00000000: 74 68 69 73 20 69 73 20 61 20 73 74 72 69 6E 67 this is a string
00000010: 00
Run Code Online (Sandbox Code Playgroud)
使用重定位表将another_string1变量名称连接到文字数据.
请注意,字符串文字对象的名称显然基于文字字符串的内容,但有一些错位.我怀疑任何地方都有记录(但是谁知道 - 也许有人对它进行了逆向设计).
无论如何,如果你想要以相同的方式处理程序集文件中的文字,你需要安排文字以相同的方式放在目标文件中.老实说,我不知道汇编程序可能有什么(如果有的话)机制.将对象放在"COMDAT"部分可能非常简单 - 将对象的名称基于字符串内容(并以适当的方式修改)是另一个故事.
除非有一些专门支持这种情况的汇编指令/关键字,否则我认为你可能会失败.当然可能有一个,但我已经足够生气了ml.exe,不知道,快速浏览一下这些吝啬的MSDN文档ml.exe没有任何跳出来.
但是,如果您愿意将sting文字放在C文件中并通过externs在汇编代码中引用它们,它应该可以工作.然而,这基本上是Mark Ransom在他对这个问题的评论中提倡的.
| 归档时间: |
|
| 查看次数: |
2552 次 |
| 最近记录: |