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

函数返回后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;
}

原代码的其他问题修正

  1. catch (std::exception e) 应改为catch (const std::exception& e),用引用接收异常避免不必要的拷贝,同时const修饰更安全。
  2. throw new std::exception(errmsg.c_str()); 会抛出堆分配的异常指针,调用者需手动delete,极易造成内存泄漏,应直接抛出栈上的标准异常对象(如std::runtime_error)。
  3. if (!file.is_open()) { throw; } 属于冗余代码,因为已经通过file.exceptions设置了异常触发条件,open失败会自动抛出异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 04:34:56