g++ 7.5.0使用-O3编译时调用std::to_string(INFINITY)触发段错误
g++ 7.5.0使用-O3编译时调用std::to_string(INFINITY)触发段错误
看起来你碰到了一个挺有意思的编译器优化相关bug,我来帮你拆解下问题和解决办法:
问题复现场景
你的环境和触发条件很明确:
- 编译器版本:
gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~16.04) - 编译命令:
g++ -O3 <file> - 触发点:代码中调用
std::to_string(INFINITY) - 特殊现象:注释掉未被调用的
test()函数后段错误消失;改用非-O3优化等级(比如默认-O0)也不会触发问题。
你的测试代码如下:
#include <iostream> #include <cmath> #include <string> void test() { std::cout << "test: " << std::endl; std::cout << "init" << std::endl; std::cout << "inf" << std::endl; std::cout << std::to_string(INFINITY) << std::endl; std::cout << "init done" << std::endl; } int main () { std::cout << "test: " << std::endl; std::cout << "init" << std::endl; std::cout << "inf" << std::endl; std::cout << std::to_string(INFINITY) << std::endl; std::cout << "init done" << std::endl; return 0; }
段错误的调用栈信息:
Program received signal SIGSEGV, Segmentation fault. 0x0000000000400f01 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > __gnu_cxx::__to_xstring<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, char>(int (*)(char*, unsigned long, char const*, __va_list_tag*), unsigned long, char const*, ...) [clone .constprop.20] () (gdb) bt #0 0x0000000000400f01 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > __gnu_cxx::__to_xstring<std::__cxx11::basic_string<char, std::char_traits<cha r>, std::allocator<char> >, char>(int (*)(char*, unsigned long, char const*, __va_list_tag*), unsigned long, char const*, ...) [clone .constprop.20] () #1 0x0000000000400c63 in main ()
问题原因
这是g++ 7.x版本在-O3优化等级下的一个已知bug:当编译器处理std::to_string(INFINITY)或std::to_string(NAN)时,若存在未被调用的函数(比如你的test()),优化器会错误地篡改字符串格式化的内部逻辑,导致内存访问越界触发段错误。而注释掉test()后,编译器的优化路径改变,刚好避开了这个bug的触发条件。
解决办法
你可以从以下几个方向解决这个问题:
- 替换格式化方式:改用
std::ostringstream来格式化无穷大/NaN值,这是最稳妥的兼容方案:#include <sstream> // ... std::ostringstream oss; oss << INFINITY; std::cout << oss.str() << std::endl; - 调整优化等级:暂时使用
-O2代替-O3,或者直接使用默认优化等级,避开触发bug的优化逻辑; - 升级编译器:将g++版本升级到8.0及以上,这个bug在后续的编译器版本中已经被官方修复。
备注:内容来源于stack exchange,提问作者cryptickey
相关产品推荐
相关产品推荐

