GCC 9.4.0下访问ostringstream::str().c_str()崩溃,是代码问题还是编译器Bug?
问题分析:代码编写错误而非编译器Bug
核心原因:临时字符串对象的生命周期问题
这段代码的崩溃根源在于对outstr.str().c_str()的错误使用:
ostringstream::str()会返回一个临时的std::string对象,该对象的生命周期仅局限于当前表达式执行期间。- 调用
c_str()得到的是这个临时std::string内部字符数组的指针,但在表达式const char *cptr = outstr.str().c_str();执行完毕后,临时std::string会立即被销毁,其内部的字符数组也会被释放。 - 此时
cptr就变成了悬空指针,后续访问该指针属于C++标准定义的未定义行为,触发崩溃是完全符合规则的结果。
修复方案
要解决这个问题,需要先保存str()返回的std::string对象,延长其生命周期后再获取指针:
#include <iostream> #include <sstream> #include <cstdarg> using std::cout; using std::ostringstream; using std::string; void log(const char *fname, int lineno) { ostringstream outstr; outstr << fname << ", line " << lineno; cout << outstr.str() << '\n'; string temp_str = outstr.str(); // 保存临时对象,延长生命周期 const char *cptr = temp_str.c_str(); cout << "cptr is at " << (void*) cptr << ", and is " << cptr; // 正常运行 } int main() { log("foo.cc", 100); }
补充说明
Valgrind的报错和运行时崩溃都是悬空指针访问的典型表现,该问题与编译器版本(GCC 9.4.0)无关,更换其他符合C++标准的编译器(如Clang)也会出现相同问题。
内容的提问来源于stack exchange,提问作者QF0
相关产品推荐
相关产品推荐

