自定义MyException类为何在Linux下产生乱码信息?
问题分析:自定义异常类在Linux下输出乱码的原因
先看你的异常类实现代码:
class MyException: public std::exception { private: std::string m_message; bool m_internalError; public: MyException(bool internal_err, std::string msg) : m_message(std::move(msg)), m_internalError(internal_err) { } const char* what() const noexcept override { std::ostringstream msg; msg << m_internalError << ": " << m_message; std::string full_msg = msg.str(); return full_msg.c_str(); } };
问题描述
上述自定义异常类在Windows系统中运行正常,但在Linux系统下会输出乱码信息。若从ostringstream中移除m_message则恢复正常,请问该问题的原因是什么?
核心原因
问题本质是悬空指针引发的未定义行为,差异源于不同系统的内存管理策略:
what()函数里的full_msg是局部字符串对象,函数执行完毕后,该对象会被销毁,其内部的字符数组也会被回收。而你返回的full_msg.c_str()指向的就是这块即将被释放的内存,属于悬空指针。- Windows和Linux的栈内存处理逻辑不同:Windows下函数返回后,栈上的内存可能暂时不会被覆盖,所以悬空指针还能侥幸读到原有内容;但Linux下栈内存会被快速复用或清理,此时访问悬空指针就会得到乱码或无意义的数据。
- 移除
m_message后看似正常只是巧合:即便去掉m_message,悬空指针的问题依然存在,只是生成的字符串更短,内存覆盖的概率更低,但这依然是未定义行为,随时可能出问题。
正确解决方式
应该把拼接好的完整消息存储为异常类的成员变量,确保返回的指针指向的内存不会随函数结束而销毁。比如在构造函数中完成消息拼接:
class MyException: public std::exception { private: std::string m_fullMessage; public: MyException(bool internal_err, std::string msg) { std::ostringstream oss; oss << internal_err << ": " << msg; m_fullMessage = oss.str(); } const char* what() const noexcept override { return m_fullMessage.c_str(); } };
内容的提问来源于stack exchange,提问作者Raj Kumar
相关产品推荐
相关产品推荐

