gpt4 book ai didi

c - Visual C++ 2015/GL(全程序优化)和/OPT :REF (optimize references) prevent static initializers being called

转载 作者:太空宇宙 更新时间:2023-11-03 23:44:37 24 4
gpt4 key购买 nike

简介: C++ 中的全局静态对象在 main() 启动之前进行初始化。考虑:

#include <stdio.h>
int calc_it() {
return 1;
}
int glob = calc_it();
int main() {
printf("glob = %d\n", glob);
return 0;
}

输出是 glob = 1,因为 calc_it() 和赋值是在 main() 开始之前执行的。代码的顺序与它无关。

现在想象一下,您有多个包含类似代码的源文件,并且进一步想象它们以某种方式相互依赖(无论出于何种原因,您都需要特定的执行顺序。我们先不讨论这是好设计还是坏设计。)

执行顺序未由标准定义,但在 Visual C++ 中存在对它们施加特定顺序的方法。对于全局静态对象,可以在对象定义前使用#pragma init_seg(SECTIONNAME)来指定某个section name

但这最终只会导致编译器将 (__cdecl *)(void) 指针指向某些链接器部分中的函数(它们都以 .CRT$XC 开头) >).在链接器确定内存布局之前,节名称按字典顺序排序。默认部分名称是 .CRT$XCU。然后C/C++初始化代码将.CRT$XCA.CRT$XCZ这几段内容看成是函数指针,一一调用。

我们也可以使用 #pragma data_seg(SECTIONNAME) 指令手动完成此操作。所以这个:

#include <stdio.h>
void hi_there() {
printf("hi there!\n");
}
int main() {
printf("bye!\n");
return 0;
}
#pragma data_seg(".CRT$XCM")
typedef void (__cdecl *atexit_func)(void);
atexit_func _init_ptr[] = { hi_there };

将输出:

hi there!
bye!

这有多好? :)

问题描述:AFAIK,自 Visual C++ 2015 起,如果您将 /GL 选项(全程序优化)与 /OPT:REF 链接器选项(删除未使用的功能和数据)。原因可能是从链接器的角度来看,从未使用过 _init_ptr。在较旧的 Visual Studio 版本中,这仍然有效,因为它们从未删除未使用的数据,仅使用过的代码

问题:如何避免仅针对单个符号出现这种情况?

最佳答案

Visual Studio 链接器有一个选项来包含某个符号,无论它是否被引用:/INCLUDE:symbol。Visual C++ 提供了一种将此链接器选项添加到已编译目标文件的方法:#pragma comment(linker, "/include:symbol")

即使使用 cl/O2/GL x.cpp/link/OPT:REF(即,对于 x86,32 位)编译,以下代码也会运行:

#include <stdio.h>
void hi_there() {
printf("hi there!\n");
}
int main() {
printf("bye!\n");
return 0;
}
#pragma data_seg(".CRT$XCM")
typedef void (__cdecl *atexit_func)(void);
extern "C" atexit_func _init_ptr[] = { hi_there };
#pragma comment(linker, "/include:__init_ptr")

请注意 /include:extern "C" 之后的前导额外下划线,以防止名称混淆。

更新:为了使代码也能针对 x64 进行编译,我们需要添加一些额外内容:

#include <stdio.h>
void hi_there() {
printf("hi there!\n");
}
int main() {
printf("bye!\n");
return 0;
}

#ifdef _M_X64
#define INCLUDE_SYM(s) comment(linker, "/include:" #s)
#else
#define INCLUDE_SYM(s) comment(linker, "/include:_" #s)
#endif

#pragma data_seg(".CRT$XCM")
#pragma section(".CRT$XCM", read)
typedef void (__cdecl *atexit_func)(void);
extern "C" atexit_func _init_ptr[] = { hi_there };
#pragma INCLUDE_SYM(_init_ptr)

关于c - Visual C++ 2015/GL(全程序优化)和/OPT :REF (optimize references) prevent static initializers being called,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36841629/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com