You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CentOS7迁移RHEL8后C++代码返回无效字符串问题排查

问题:CentOS 7迁移至RHEL 8后std::runtime_error的what()返回垃圾值

我们公司有一套在CentOS 7上稳定运行多年的框架,迁移至RHEL 8后部分单元测试失败,其中一个问题是std::runtime_error的what()返回垃圾值。我写了一段极简C++代码复现该问题:这段代码在CentOS 7运行正常,但在RHEL 8中返回无效值。

复现代码

#include <sstream>
#include <iostream>

const char * getString() {

    std::ostringstream oss;
    oss << "some stuff to return" << std::endl;

    std::cout << "value to return: " << oss.str().c_str() << std::endl;

    return oss.str().c_str();
}

int
main(int argc, char ** argv) {

    std::string value = getString();
    std::cout << "value returned: " << value << std::endl;

    return 0;
}

CentOS 7运行输出

[user@localhost ~]$ ./a.out
value to return: some stuff to return

value returned: some stuff to return

RHEL 8运行输出

[user@localhost badoverload]$ ./a.out
value to return: some stuff to return

value returned: `

提问

请问是否是值超出作用域导致内存不可用,只是CentOS7中内存恰好未被修改,还是存在其他原因?


回答

没错,核心原因就是超出作用域导致内存被释放,CentOS 7里只是运气好内存没被覆盖而已。

看你的代码:getString()里返回的是oss.str().c_str(),这里oss.str()会生成一个临时的std::string对象,c_str()返回的是这个临时对象内部的字符数组指针。等这条语句执行完,这个临时std::string就会被销毁,它管理的内存也会被释放。

回到main函数里用std::string value = getString();时,你拿到的是一个指向已经被释放内存的指针,这时候去构造新的std::string属于未定义行为——也就是说C++标准没规定这种情况会发生什么,完全取决于编译器、操作系统、内存管理机制的具体实现。

CentOS 7用的是旧版GCC(比如4.8.x),可能在临时对象销毁后,内存暂时没被其他操作覆盖,所以指针还能读出原来的内容;而RHEL 8用的是新版GCC(比如8.x),可能内存被立即清零或者被其他数据覆盖了,所以读出来就是垃圾值。

解决方法很简单,直接返回std::string而不是const char*:

std::string getString() {
    std::ostringstream oss;
    oss << "some stuff to return" << std::endl;
    std::cout << "value to return: " << oss.str() << std::endl;
    return oss.str();
}

这样std::string会正确地把数据复制一份返回,不会出现内存悬空的问题。

内容的提问来源于stack exchange,提问作者mybodycravesbutterygoodness

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 09:52:50