【问题标题】:Malloc not working after some calls (C, compiled with gcc for MinGW-W64 on Windows 10)Malloc 在某些调用后无法工作(C,在 Windows 10 上使用 gcc 为 MinGW-W64 编译)
【发布时间】:2019-10-21 12:20:18
【问题描述】:

我需要在 Windows 上测试我的项目的性能。
我有一个数组数组rede_conexoes,并在循环中分配每个位置,但经过一些迭代后,malloc 函数不起作用并突然停止我的进程,然后我什至可以测试返回值并且没有显示错误消息.

代码在 Windows 10 上的 WSL(Linux 的 Windows 子系统)上运行良好。为了在 Windows 上本地测试代码,我为 gcc 编译器安装了 Mingw-w64(找不到更好的解决方案,因为支持需要 OpenMP)。
这是带有malloc 函数的sn-p:

bool **rede_conexoes = (bool**) malloc(num_PL * sizeof(bool*));
...
for(int i = 0; i < num_PL; i++){
    rede_conexoes[i] = (bool*)malloc(num_PL*sizeof(bool)); // <- Error occurs here
    if(rede_conexoes[i] == NULL) exit(1); // <- Can't get to this line after the error
    for(int j = 0; j < num_PL; j++)
        fscanf(model, "%d", (int*)&rede_conexoes[i][j]);
}

我不明白如何在 WSL 上运行而没有问题,但在 Windows 上它会崩溃并且没有错误消息。
我注意到当num_PL 大于2^3 = 8 时它开始失败,如果num_PL 大于2^15 = 32768 在Linux 上没有问题。我在命令提示符(cmd)和PowerShell上测试了gcc创建的.exe,结果都一样。

【问题讨论】:

  • 文件有足够的数字吗?
  • 顺便说一句,最好[不要强制转换 malloc 的结果] (stackoverflow.com/questions/605845/…)
  • fscanf(model, "%d", (int*)&amp;rede_conexoes[i][j]); 如果sizeof(bool) &lt; sizeof(int) 写入越界(在许​​多实现中都是如此),并且还可能创建陷阱表示。并且指针可能与int 对齐不正确。您应该读入一个int 变量,然后分配给数组位置
  • fscanf() 严重损坏;你告诉它指向_Bool 的指针是指向int 的指针。你好未定义的行为。
  • 另外,您应该发布minimal reproducible example,因为问题可能是程序中其他地方的堆损坏并且恰好出现在此时

标签: c windows gcc malloc mingw


【解决方案1】:

当您将最后一个数字(i == num_PL - 1j == num_PL - 1)读入&amp;rede_conexoes[i][j] 时,您已为bool(通常为 1 个字节)分配空间,但您已要求运行时读取int(通常为 4 或有时为 8 个字节)。这可能会在您分配的空间末尾写入几个字节。这会导致未定义的行为,从而导致程序看起来正常工作、行为不端或崩溃。

根据num_PL 的值以及运行时处理内存管理的方式,这些额外的几个字节可能会覆盖运行时用来跟踪内存块的一些控制数据。根据被覆盖的内容和使用方式,这可能会导致您遇到崩溃。

如 cmets 中所述,一种解决方案是将整数读入 int 类型的局部变量,然后将其分配给您的 bool 数组。

【讨论】:

  • 更改了fscanf 以将其存储在一个临时变量中,然后将其分配给rede_conexoes[i][j],它解决了问题!我测试了boolbool*intint* 的大小,指针在 Linux 上使用 8 个字节,但在 Windows 上使用 4 个字节,这可能是未定义行为的原因。
【解决方案2】:

也许,操作系统不允许调用进程为您提供所有内存。

假设您正在使用二次二维 (2D) 数组:

2^15 * 2^15 = 32.768 * 32.768 = 1.073.741.824 booleans!

如果您在 32 位架构中运行此代码sizeof(bool*) = 4

1.073.741.824 * 4 = 4.294.967.296 (4GB)

如果您在 64 位架构中运行此代码sizeof(bool*) = 8

1.073.741.824 * 8 = 8.589.934.592 (8GB)

所有内存都可用于调用进程?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多