BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / cpp / #101949同步于 2022/5/25
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖

【问题】extern constexpr 问题

YiYeShu
2022/5/25镜像同步5 回复
```c++ // foo.cpp extern constexpr int g_z{3}; ``` ```c++ // main.cpp #include <iostream> extern int g_z; int main() { std::cout << g_z << '\n'; ++g_z; std::cout << g_z << '\n'; return 0; } ``` ```bash # 编译指令 g++ main.cpp foo.cpp -std=c++17 ``` 问题:为什么编译链接不报错,非要等到执行到 `++g_z` 这一句才蹦出个错误出来: ``` terminated by signal SIGBUS (Misaligned address error) ```
订阅后,新回复会通过你的通知中心匿名送达。
5 条回复
markovwang机器人#1 · 2022/5/25
我刚也试了下, gcc 11.2的行为和楼主一样; 但是用msvc 就过不了编译,提示没找到符号, 然后我就分别dump了g++和msvc生成的foo.cc的obj文件, 发现g++生成的符号虽然在rodata区, 但是并没有const约束, 而msvc生成的符号是有const约束的...不知道是不是这个导致的, 求问大神
markovwang机器人#2 · 2022/5/25
【 在 YiYeShu 的大作中提到: 】 : [md] : ```c++ : // foo.cpp : ...................
pyth0n机器人#3 · 2022/5/25
首先,++g_z这一行当然是有问题的,因为它是一个const变量,编译器会把它放在只读的数据段中。对只读的数据段进行写入当然会触发 memory access violation。 然后问题:为什么编译链接不报错,非要等到执行到++g_z 这一句才蹦出个错误出来 两个直接原因: 1. 这个问题无法被编译器发现,因为编译器只对当前文件进行编译,看不到其它文件,因此也无法得知 g_z 的定义 2. 编译器的 name mangling 产生的符号不携带类型,因此链接器(ld)也无法发现这个问题 可以用以下命令查看 foo.cpp 输出的符号: pyth0n@precision3630tower /tmp $ gcc -c foo.cc -o foo.o pyth0n@precision3630tower /tmp $ nm -a foo.o 0000000000000000 a foo.cc 0000000000000000 R g_z 从上文可以看出,foo.cpp导出的符号为 g_z,没有携带 constexpr int 类型,因此链接器无法发现 所以,更进一步地,即使两个文件声明的变量类型完全不一样,编译也能通过,只是结果不是想要的而已。例如: // foo.cpp extern int g_z; int g_z = 3; // main.cpp #include <iostream> extern double g_z; // NOTE: should be `extern int g_z` here int main() { std::cout << g_z << '\n'; // OUTPUT: 1.4822e-323 ++g_z; std::cout << g_z << '\n'; // OUTPUT: 1 return 0; }
YiYeShu机器人#4 · 2022/5/25
好的,多谢 【 在 pyth0n 的大作中提到: 】 : 首先,++g_z这一行当然是有问题的,因为它是一个const变量,编译器会把它放在只读的数据段中。对只读的数据段进行写入当然会触发 memory access violation。 : : 然后问题:为什么编译链接不报错,非要等到执行到++g_z 这一句才蹦出个错误出来 : ...................
YiYeShu机器人#5 · 2022/5/25
不同的编译器,结果不一样,这种事太烦了,[em21] 【 在 markovwang 的大作中提到: 】 : 我刚也试了下, gcc 11.2的行为和楼主一样; 但是用msvc 就过不了编译,提示没找到符号, 然后我就分别dump了g++和msvc生成的foo.cc的obj文件, 发现g++生成的符号虽然在rodata区, 但是并没有const约束, 而msvc生成的符号是有const约束的...不知道是不是这个导致的, 求问大神