函数返回后std::string内存被释放,主函数读取内容异常求助
问题:函数返回文件内容后数据丢失,输出乱码
核心原因
你返回的contents.c_str()指向的是函数内局部std::string对象contents的内部字符数组。当ReadFile函数执行完毕时,局部变量contents会被销毁,其占用的内存被系统回收,此时main函数中的指针a就变成了野指针,访问野指针属于未定义行为,因此输出乱码。
解决方案1:返回std::string(推荐)
直接返回std::string对象,利用C++的拷贝/移动语义将内容安全转移到main函数的变量中,无需手动管理内存:
#include <string> #include <fstream> #include <iostream> std::string ReadFile(const std::string& path) { std::ifstream file; try { file.exceptions(std::ifstream::failbit | std::ifstream::badbit); file.open(path); } catch (const std::exception& e) { // 用引用接收异常,避免不必要拷贝 std::string errmsg = "Unable to open file at path: " + path; std::cout << errmsg << std::endl; throw std::runtime_error(errmsg); // 抛出标准异常,避免内存泄漏 } std::string contents; try { contents = std::string{ std::istreambuf_iterator<char>{file}, {} }; } catch (const std::ifstream::failure& e) { std::cout << path << std::endl; std::cout << e.what() << std::endl; throw; // 重新抛出原异常 } std::cout << "----------------" << std::endl; std::cout << "in the function:" << std::endl; std::cout << contents << std::endl; return contents; } int main() { try { std::string a = ReadFile("test.txt"); std::cout << "----------------" << std::endl; std::cout << "in main" << std::endl; std::cout << a << std::endl; } catch (const std::exception& e) { std::cerr << "Error: " << e.what() << std::endl; return 1; } return 0; }
解决方案2:返回动态分配的char数组(不推荐,需手动管理内存)
如果必须返回const char*,需要在堆上手动分配内存并拷贝内容,同时要记得在main函数中手动释放内存,避免泄漏:
#include <string> #include <fstream> #include <iostream> #include <cstring> const char* ReadFile(const std::string& path) { std::ifstream file; try { file.exceptions(std::ifstream::failbit | std::ifstream::badbit); file.open(path); } catch (const std::exception& e) { std::string errmsg = "Unable to open file at path: " + path; std::cout << errmsg << std::endl; throw std::runtime_error(errmsg); } std::string contents; try { contents = std::string{ std::istreambuf_iterator<char>{file}, {} }; } catch (const std::ifstream::failure& e) { std::cout << path << std::endl; std::cout << e.what() << std::endl; throw; } std::cout << "----------------" << std::endl; std::cout << "in the function:" << std::endl; std::cout << contents << std::endl; // 动态分配内存,需预留字符串结束符的位置 char* result = new char[contents.size() + 1]; std::strcpy(result, contents.c_str()); return result; } int main() { const char* a = nullptr; try { a = ReadFile("test.txt"); std::cout << "----------------" << std::endl; std::cout << "in main" << std::endl; std::cout << a << std::endl; } catch (const std::exception& e) { std::cerr << "Error: " << e.what() << std::endl; delete[] a; // 异常场景也要释放内存 return 1; } delete[] a; // 手动释放堆内存 return 0; }
原代码的其他问题修正
catch (std::exception e)应改为catch (const std::exception& e),用引用接收异常避免不必要的拷贝,同时const修饰更安全。throw new std::exception(errmsg.c_str());会抛出堆分配的异常指针,调用者需手动delete,极易造成内存泄漏,应直接抛出栈上的标准异常对象(如std::runtime_error)。if (!file.is_open()) { throw; }属于冗余代码,因为已经通过file.exceptions设置了异常触发条件,open失败会自动抛出异常。
内容的提问来源于stack exchange,提问作者Henry Boyer
相关产品推荐
相关产品推荐

