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

打开输出文件流触发STATUS_HEAP_CORRUPTION(错误码3221226356)排查

堆损坏(STATUS_HEAP_CORRUPTION)问题排查与修复

我做学校作业拓展项目,写了一个从程序运行目录开始,在每个子文件夹写入文件的程序,包含递归遍历和文件写入函数。非调试模式下,第一个子文件夹中创建ofstream(第二次写入文件时)触发"exited with code=3221226356"错误(对应STATUS_HEAP_CORRUPTION);移除递归调用后,主目录下文件能正常写入。除输入变量char*外无其他数组,请问是什么原因导致这个内存问题?

#include <dirent.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include <time.h>
#include <limits.h>

const char * separator_char() {
    #ifdef _WIN32
        return "\\";
    #else
        return "/";
    #endif
}

void createCopy(const char * path) {
    const char * separator = separator_char();
    char * file_name_path = strdup(path);
    strcat(file_name_path, separator);
    printf("Writing Roberto.txt...\n");
    strcat(file_name_path, "Roberto.txt");
    std::ofstream dst(file_name_path, std::ios::binary | std::ofstream::trunc); // ERROR HERE
    dst << "test";
    printf("Wrote %s\n", file_name_path);
    dst.close();
}

void multiply(const char * path) {
    const char * separator = separator_char();
    char * path_2 = strdup(path);
    strcat(path_2, separator);
    DIR * dir = opendir(path);
    struct dirent * entry = readdir(dir);
    while (entry != NULL) {
        if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0 && entry->d_type == DT_DIR) {
            char * path_3 = strdup(path_2);
            strcat(path_3, entry->d_name);
            printf("%s\n", path_3);
            createCopy(path_3);
            multiply(path_3);
        }
        entry = readdir(dir);
    }
    closedir(dir);
}

int main(int argc, char ** argv) {
    const char * PATH = ".";
    multiply(PATH);
    getchar();
    return 0;
}

问题原因

核心问题是手动内存管理时的缓冲区越界写入,直接破坏了堆结构:

  • strdup(path)仅分配刚好容纳path字符串(含末尾\0)的内存空间,没有预留后续追加内容的空间。
  • 后续调用strcat追加分隔符和文件名时,会越界写入到堆内存的其他区域,破坏堆的元数据。
  • 第一次写入主目录时,堆布局可能刚好未触发崩溃,但递归进入子文件夹后,多次堆分配/释放操作让越界写入的破坏暴露,最终触发STATUS_HEAP_CORRUPTION。
  • 同样的越界问题也存在于multiply函数中的path_2:strdup(path)后直接strcat追加分隔符,同样会超出内存范围。

另外代码未释放strdup分配的内存,会造成内存泄漏,但这不是触发堆损坏的直接原因。

修复方案

用C++的std::string替代手动char*内存管理,它会自动处理内存扩容,彻底避免越界问题。修改后的关键代码示例:

void createCopy(const std::string& path) {
    const char* separator = separator_char();
    std::string file_name_path = path + separator + "Roberto.txt";
    printf("Writing Roberto.txt...\n");
    std::ofstream dst(file_name_path, std::ios::binary | std::ofstream::trunc);
    dst << "test";
    printf("Wrote %s\n", file_name_path.c_str());
    dst.close();
}

void multiply(const std::string& path) {
    const char* separator = separator_char();
    std::string path_2 = path + separator;
    DIR* dir = opendir(path.c_str());
    struct dirent* entry = readdir(dir);
    while (entry != NULL) {
        if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0 && entry->d_type == DT_DIR) {
            std::string path_3 = path_2 + entry->d_name;
            printf("%s\n", path_3.c_str());
            createCopy(path_3);
            multiply(path_3);
        }
        entry = readdir(dir);
    }
    closedir(dir);
}

int main(int argc, char** argv) {
    std::string PATH = ".";
    multiply(PATH);
    getchar();
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 03:21:10