C++ 哪个部分将全局常量变量存储在C++;可执行文件?
据我所知,在C/C++程序中,全局常量变量将存储在可执行文件的.text(或.data-我不确定)部分。但当我试图验证这一点时,我遇到了麻烦 我有一个程序,它有一个全局常量变量,如下所示:C++ 哪个部分将全局常量变量存储在C++;可执行文件?,c++,c,C++,C,据我所知,在C/C++程序中,全局常量变量将存储在可执行文件的.text(或.data-我不确定)部分。但当我试图验证这一点时,我遇到了麻烦 我有一个程序,它有一个全局常量变量,如下所示: const unsigned char data[2030320] = { 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x04, 0x00, 0x30, 0x42, 0x41, 0x53, 0x45, 0xda, 0xec, 0
const unsigned char data[2030320] =
{
0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x04, 0x00, 0x30, 0x42, 0x41, 0x53, 0x45,
0xda, 0xec, 0xe7, 0xed, 0x00, 0x00, 0x01, 0x3c, 0x00, 0x00, 0x00, 0xc6, 0x47, 0x44, 0x45, 0x46,
0x50, 0x4b, 0x6e, 0x76, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x4e, 0x47, 0x50, 0x4f, 0x53,
0x64, 0x0a, 0x6e, 0x00, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x0a, 0xdc, 0x47, 0x53, 0x55, 0x42,
0x41, 0xfc, 0x50, 0x71, 0x00, 0x00, 0x0d, 0x30, 0x00, 0x00, 0x44, 0x16, 0x4c, 0x49, 0x4e, 0x4f,
0x96, 0xa8, 0xc8, 0xcc, 0x00, 0x00, 0x51, 0x48, 0x00, 0x00, 0x00, 0x12, 0x4f, 0x53, 0x2f, 0x32,
0x63, 0x8d, 0x51, 0xdd, 0x00, 0x00, 0x51, 0x5c, 0x00, 0x00, 0x00, 0x60, 0x63, 0x6d, 0x61, 0x70,
0xc7, 0xfa, 0x84, 0xe4, 0x00, 0x00, 0x51, 0xbc, 0x00, 0x00, 0x8c, 0xf2, 0x67, 0x61, 0x73, 0x70,
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0xde, 0xb0, 0x00, 0x00, 0x00, 0x08, 0x67, 0x6c, 0x79, 0x66,
0x31, 0xb9, 0x1a, 0xce, 0x00, 0x00, 0xde, 0xb8, 0x00, 0x1b, 0x4e, 0x90, 0x68, 0x65, 0x61, 0x64,
0xfe, 0x4d, 0xbc, 0xcd, 0x00, 0x1c, 0x2d, 0x48, 0x00, 0x00, 0x00, 0x36, 0x68, 0x68, 0x65, 0x61,
0x07, 0x6b, 0x21, 0x2a, 0x00, 0x1c, 0x2d, 0x80, 0x00, 0x00, 0x00, 0x24, 0x68, 0x6d, 0x74, 0x78,
0x04, 0x8c, 0x39, 0x67, 0x00, 0x1c, 0x2d, 0xa4, 0x00, 0x00, 0x7b, 0xf4, 0x6c, 0x6f, 0x63, 0x61,
0x72, 0x06, 0x3f, 0xca, 0x00, 0x1c, 0xa9, 0x98, 0x00, 0x00, 0x7b, 0xf8, 0x6d, 0x61, 0x78, 0x70,
0x21, 0x89, 0x01, 0x63, 0x00, 0x1d, 0x25, 0x90, 0x00, 0x00, 0x00, 0x20, 0x6e, 0x61, 0x6d, 0x65,
0xc0, 0xe5, 0xda, 0x3d, 0x00, 0x1d, 0x25, 0xb0, 0x00, 0x00, 0x04, 0x3d, 0x70, 0x6f, 0x73, 0x74,
0x0a, 0xfb, 0xdd, 0xeb, 0x00, 0x1d, 0x29, 0xf0, 0x00, 0x01, 0x54, 0xe2, 0x70, 0x72, 0x65, 0x70,
...
};
但当使用dumpbin.exe(在Windows上)检查程序的.exe文件中节的大小时。如果我删除变量,结果与结果相同,它总是如下所示
4B1000 .data
1000 .idata
3000 .rdata
2000 .reloc
1000 .rsrc
4000 .text
10000 .textbss
有谁能帮我解释一下吗?如果能证明变量从未被引用,编译器很可能会优化掉变量。不幸的是,编译器一次只能看到一个翻译单元(包含在
#include
之后的源文件),因此禁止编译器优化未使用的全局变量。链接器拥有所有转换单元的知识,因此它可以(并且将)对未使用的全局变量执行优化
以下代码使用MSVC编译(/O2
指定):
创建以下PE文件:
File Type: EXECUTABLE IMAGE
Summary
1000 .data
1000 .gfids
1000 .rdata
1000 .reloc
1000 .rsrc
1000 .text
如果使用全局,则它将存储在PE文件的.rdata
段中(注意,如果全局为非常量,则它将被放置在.data
段中,因为.rdata
是只读的)。例如:
const char a[1000000] = { 0 };
int main()
{
char c = a[1];
return 0;
}
和dumpbin
输出:
File Type: EXECUTABLE IMAGE
Summary
1000 .data
1000 .gfids
F5000 .rdata
1000 .reloc
1000 .rsrc
1000 .text
但是在下面的示例中,a
仍然可以优化,因为c
是未引用的局部变量。我发现,在MSVC/GS
中,编译器开关(它表示整个程序优化,并强制执行/LTCG
,它将代码生成延迟到链接阶段,以便执行跨文件优化的所有信息都可用)实际上阻止了这种优化
在没有
/LTCG
和/GS
的情况下,它按预期进行了优化。添加/GS
将禁用全局数据优化,必须通过添加/Gw
来启用全局数据优化,如果数据未在任何地方使用,则生成的文件甚至不需要包含数据-编译器或链接器可以删除它。您是对的。我已经确认了。但是如果全局变量是const,则它是正确的。如果我将数据[]从常量更改为非常量,即使未使用,它也始终存储在.data中。你能帮我解释一下吗?常量不能进入。data
,因为它们是只读的-。rdata
表示PE规范中规定的“只读初始化数据”。编译器可能无法优化未使用的非常量全局变量。对我来说(MSVC),未使用的非常量全局值不能进入PE。听到编译器在第二个示例中没有优化数组,我感到震惊。@MikeMB我很欣赏讽刺。移除了那个不幸的sentence@mpiatek:一点也不讽刺。我真的希望编译器能够优化全局数组,即使您以示例中所示的方式使用它,因为这种用法本身是可以删除的。
File Type: EXECUTABLE IMAGE
Summary
1000 .data
1000 .gfids
F5000 .rdata
1000 .reloc
1000 .rsrc
1000 .text