这真的很奇怪!我简化了您的代码示例并添加了一些变量和函数,以查看观察结果是否普遍有效。
uc.h:
#include <string>
extern std::string mymystring1;
extern std::string mymystring2;
extern int mymyx1;
extern int mymyx2;
int mymyf1();
int mymyf
uc.cpp:
#include <string>
std::string mymystring1 ="This is a very simple test what happens if fdata sections did not work!";
std::string mymystring2 ="This variable should be used";
int mymyx1 = 11111; // unused
int mymyx2 = 22222;
int mymyf1() { return 1; } // unused
int mymyf2() { return 2; }
主.cpp:
#include "uc.h"
int main() {
std::cout << mymystring1 << std::endl;
std::cout << mymyx1 << std::endl;
std::cout << mymyf1() << std::endl;
return 0;
}
即使我将 uc.cpp 作为库进行编译和链接,我也会在我的代码中链接到未使用的字符串对象。
63: 00000000004041c0 32 OBJECT GLOBAL DEFAULT 24 _Z11mymystring1B5cxx11
78: 00000000004041a0 32 OBJECT GLOBAL DEFAULT 24 _Z11mymystring2B5cxx11
90: 0000000000404070 4 OBJECT GLOBAL DEFAULT 23 mymyx1
查看 uc.o 文件objdump -h uc.o
11 .data.mymyx2 00000004 0000000000000000 0000000000000000 000001d0 2**2
CONTENTS, ALLOC, LOAD, DATA
12 .data.mymyx1 00000004 0000000000000000 0000000000000000 000001d4 2**2
CONTENTS, ALLOC, LOAD, DATA
13 .bss._Z11mymystring2B5cxx11 00000020 0000000000000000 0000000000000000 000001e0 2**5
ALLOC
14 .bss._Z11mymystring1B5cxx11 00000020 0000000000000000 0000000000000000 000001e0 2**5
ALLOC
我们看到 mymyx1 和 mymyx2 的数据位于不同的数据部分中。字符串数据生成 bss 部分?数据在哪里?
OK,我们来看一下:objdump -s go
.rodata 部分的内容:
402000 62617369 635f7374 72696e67 3a3a5f4d basic_string::_M
402010 5f636f6e 73747275 6374206e 756c6c20 _construct null
402020 6e6f7420 76616c69 64005468 69732069 not valid.This i
402030 73206120 76657279 2073696d 706c6520 s a very simple
402040 74657374 20776861 74206861 7070656e test what happen
402050 73206966 20666461 74612073 65637469 s if fdata secti
402060 6f6e7320 64696420 6e6f7420 776f726b ons did not work
402070 21005468 69732076 61726961 626c6520 !.This variable
402080 73686f75 6c642062 65207573 656400 should be used.
如果我将第二个字符串移动到另一个文件,它将被删除!
.rodata 部分的内容:
402000 54686973 20697320 61207665 72792073 This is a very s
402010 696d706c 65207465 73742077 68617420 imple test what
402020 68617070 656e7320 69662066 64617461 happens if fdata
402030 20736563 74696f6e 73206469 64206e6f sections did no
402040 7420776f 726b2100 t work!.
对我来说,这只是一个编译器/链接器错误!
来自 J.Schulke 的回答:
静态成员变量不能仅仅被优化掉,因为它们可以在多个翻译单元中访问。必须对它们进行编译,以便链接器知道何时在不同的地方使用了相同的静态变量。
它们必须被编译,但如果它们从未被访问过,它们可以在链接阶段被删除。如上面的代码所示,如果不使用函数和整数变量,则会删除它们,但std::string
如果它们与使用的数据位于同一文件中,则不会删除 vars。如果我们将每个 std::string 变量移动到单独的文件中并通过静态库链接,它们就会被移出。如果我们有,这也应该发生-fdata-sections
,但在这里不工作!为什么?我不知道。