从shared_ptr<std::string>返回const char*后无法在std::cout中显示字符
代码问题排查及修复
问题代码
#include <iostream> #include <string> const char* read_from_stdin(void) { std::shared_ptr<std::string> m_buffer(new std::string); std::getline(std::cin, *m_buffer); if (!std::cin.good()) return nullptr; while (!m_buffer->empty() && (m_buffer->back() == '\r') || (m_buffer->back() == '\n')) { m_buffer->pop_back(); } return reinterpret_cast<const char*>(m_buffer->c_str()); } int main() { std::cout << "You entered: " << read_from_stdin() << "\n"; }
运行环境
Windows 11系统,使用Microsoft Visual Studio调试模式运行,暂未检查UTF-8编码问题。
运行现象
程序输出乱码内容,而非输入的正常文本。调试时可观察到shared_ptr<T>对象内部[ptr]指向的字符为正常输入的英文。
问题根源
这段代码存在悬空指针问题:read_from_stdin函数中的m_buffer是局部shared_ptr,函数执行完毕返回时,该智能指针会被销毁,其管理的std::string对象也会随之释放。但函数返回的c_str()是指向该string内部缓冲区的指针,此时缓冲区已被释放,后续在main中访问该指针属于未定义行为,表现为输出乱码。另外原代码的逻辑运算符优先级存在错误,&&优先级高于||,导致循环条件不符合预期。
修复方案
方案一:返回std::string对象(推荐)
直接返回字符串对象,利用C++返回值优化避免额外拷贝,同时保证对象生命周期正常,还修正了逻辑运算符优先级问题:
#include <iostream> #include <string> std::string read_from_stdin(void) { std::string m_buffer; std::getline(std::cin, m_buffer); if (!std::cin.good()) return {}; while (!m_buffer.empty() && (m_buffer.back() == '\r' || m_buffer.back() == '\n')) { m_buffer.pop_back(); } return m_buffer; } int main() { std::cout << "You entered: " << read_from_stdin() << "\n"; }
方案二:延长字符串生命周期(不推荐)
若必须返回const char*,需确保string对象生命周期覆盖指针使用周期,比如将shared_ptr改为全局变量:
#include <iostream> #include <string> #include <memory> std::shared_ptr<std::string> global_buffer; const char* read_from_stdin(void) { global_buffer.reset(new std::string); std::getline(std::cin, *global_buffer); if (!std::cin.good()) return nullptr; while (!global_buffer->empty() && (global_buffer->back() == '\r' || global_buffer->back() == '\n')) { global_buffer->pop_back(); } return global_buffer->c_str(); } int main() { std::cout << "You entered: " << read_from_stdin() << "\n"; }
注:全局变量会带来额外的维护问题,非必要不建议使用。
内容的提问来源于stack exchange,提问作者Alix Blaine
相关产品推荐
相关产品推荐

