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

使用char指针构造std::string触发bad_alloc异常的问题求助

问题排查与修复方案

我来帮你揪出触发bad_alloc的问题,你的代码里有几个关键错误点,咱们一个个拆解:

1. 未处理文件打开失败的情况

如果rooms.txt不存在、权限不足或者路径错误,roomsFile.is_open()会返回false,此时你的buffer是未初始化的野指针。后续执行buffer[i] = '\0'以及把这个野指针传给std::string构造函数,会直接触发未定义行为,这很可能是bad_alloc的元凶之一。

2. while(!roomsFile.eof())的经典逻辑坑

这个循环的判断逻辑有问题:eof()只会在读取操作失败后才会被标记为true。比如当你读到文件最后一个字符时,eof()还是false,循环会继续执行,下一次roomsFile.get()会失败,但此时i已经自增了。最后执行buffer[i] = '\0'时,会越界访问你分配的数组——因为你分配的buffer大小是文件字节数roomsFile.tellg(),索引范围是0到size-1,而此时i等于size,越界写会破坏堆内存结构,导致后续std::string构造时抛出bad_alloc。

3. 内存分配的细节隐患

roomsFile.tellg()返回的是std::streampos类型,直接当成数组大小传给new char[]存在类型不匹配风险;而且你没有为末尾的'\0'额外分配空间,进一步加剧了越界问题。


修复后的代码

先给你修复loadRoomsFile函数,同时解决内存泄漏问题:

#include <fstream>
#include <iostream>
#include <string>

char* loadRoomsFile() {
    std::fstream roomsFile;
    char* buffer = nullptr; // 初始化指针,避免野指针
    int i = 0;

    std::cout << "TEST 1" << std::endl;
    roomsFile.open("rooms.txt");
    std::cout << "TEST 2" << std::endl;

    if (roomsFile.is_open()) {
        std::cout << "TEST 3" << std::endl;
        // 获取文件大小
        roomsFile.seekg(0, std::ios::end);
        std::streampos fileSize = roomsFile.tellg();
        std::cout << "TEST 4" << std::endl;

        if (fileSize <= 0) {
            // 处理空文件,返回合法的空buffer
            buffer = new char[1];
            buffer[0] = '\0';
            roomsFile.close();
            std::cout << "TEST EMPTY FILE" << std::endl;
            return buffer;
        }

        // 显式转换为size_t,为'\0'额外多分配1字节
        buffer = new char[static_cast<std::size_t>(fileSize) + 1];
        std::cout << "TEST 5" << std::endl;

        roomsFile.seekg(0, std::ios::beg);
        std::cout << "TEST 6" << std::endl;

        // 正确的读取循环:检查get()的返回值是否成功
        while (roomsFile.get(buffer[i])) {
            std::cout << "TEST WHILE" << std::endl;
            i++;
        }
        std::cout << "TEST 7" << std::endl;
    } else {
        // 文件打开失败时,返回合法的空buffer
        buffer = new char[1];
        buffer[0] = '\0';
    }

    roomsFile.close();
    std::cout << "TEST 8" << std::endl;
    buffer[i] = '\0'; // 现在不会越界,因为多分配了1字节
    std::cout << "TEST 9" << std::endl;
    std::cout << buffer << std::endl;

    return buffer;
}

int main() {
    std::cout << "----------------------------------------------------------------" << std::endl;
    std::cout << "Conference Room Manager ver. 0.1" << std::endl;
    std::cout << "Component 1/4, Bartosz Kubacki/Bartlomiej Urbanek" << std::endl;
    std::cout << "----------------------------------------------------------------" << std::endl;
    std::cout << std::endl;

    std::cout << "TEST MAIN" << std::endl;
    // 保存指针,用完记得释放,避免内存泄漏
    char* tempBuffer = loadRoomsFile();
    std::string roomsData(tempBuffer);
    delete[] tempBuffer; // 必须释放手动分配的内存

    return 0;
}

更简洁安全的方案(推荐)

其实完全不用手动管理char*内存,直接让函数返回std::string,既安全又省心,还能避免所有内存相关的问题:

#include <fstream>
#include <iostream>
#include <string>
#include <iterator>

std::string loadRoomsFile() {
    std::ifstream roomsFile("rooms.txt");
    if (!roomsFile.is_open()) {
        std::cerr << "Failed to open rooms.txt!" << std::endl;
        return "";
    }

    // 直接读取整个文件到string,一行搞定
    return std::string(std::istreambuf_iterator<char>(roomsFile), 
                       std::istreambuf_iterator<char>());
}

int main() {
    std::cout << "----------------------------------------------------------------" << std::endl;
    std::cout << "Conference Room Manager ver. 0.1" << std::endl;
    std::cout << "Component 1/4, Bartosz Kubacki/Bartlomiej Urbanek" << std::endl;
    std::cout << "----------------------------------------------------------------" << std::endl;
    std::cout << std::endl;

    std::cout << "TEST MAIN" << std::endl;
    std::string roomsData = loadRoomsFile();
    // 直接使用roomsData即可,无需手动释放内存

    return 0;
}

这个方案利用标准库的istreambuf_iterator直接读取整个文件内容到std::string,完全规避了手动分配内存的风险,代码也简洁很多。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:09:38