Malloc 在一些调用后不工作(C,在 Windows 10 上用 gcc 为 MinGW-W64 编译)
Malloc not working after some calls (C, compiled with gcc for MinGW-W64 on Windows 10)
我需要在 Windows.
上测试我的项目的性能
我有一个数组数组 rede_conexoes
,并在一个循环中分配每个位置,但经过一些迭代后 malloc
函数不起作用并突然停止我的过程,在我什至可以测试 return 值并且不显示错误消息。
该代码在 Windows 10 上的 WSL(Windows Linux 的子系统)上运行良好。为了在 Windows 上本地测试代码,我安装了 Mingw -w64 用于 gcc 编译器(找不到更好的解决方案,因为需要支持 OpenMP)。
这是带有 malloc
函数的片段:
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
大于 Linux 上的 2^15 = 32768
则没有问题。我在命令提示符 (cmd) 和 PowerShell 上测试了 gcc 创建的 .exe,结果相同。
也许,OS 不允许调用进程给你所有的内存。
假设您正在使用二次二维 (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)
调用进程可以使用所有内存吗?
当您将最后一个数字(当 i == num_PL - 1
和 j == num_PL - 1
时)读入 &rede_conexoes[i][j]
时,您已将 space 分配给 bool
(通常1 字节),但您已要求运行时读取 int
(通常为 4 字节,有时为 8 字节)。这可能会在您分配的 space 末尾写入几个字节。这会导致未定义的行为,从而导致程序看似正常工作、行为异常或崩溃。
根据 num_PL
的值以及您的运行时处理内存管理的方式,这些额外的几个字节可能会覆盖运行时用来跟踪内存块的一些控制数据。根据被覆盖的内容和使用方式,这可能会导致您遇到崩溃。
如评论中所述,一种解决方案是将整数读入 int
类型的局部变量,然后将其分配给 bool
数组。
我需要在 Windows.
上测试我的项目的性能
我有一个数组数组 rede_conexoes
,并在一个循环中分配每个位置,但经过一些迭代后 malloc
函数不起作用并突然停止我的过程,在我什至可以测试 return 值并且不显示错误消息。
该代码在 Windows 10 上的 WSL(Windows Linux 的子系统)上运行良好。为了在 Windows 上本地测试代码,我安装了 Mingw -w64 用于 gcc 编译器(找不到更好的解决方案,因为需要支持 OpenMP)。
这是带有 malloc
函数的片段:
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
大于 Linux 上的 2^15 = 32768
则没有问题。我在命令提示符 (cmd) 和 PowerShell 上测试了 gcc 创建的 .exe,结果相同。
也许,OS 不允许调用进程给你所有的内存。
假设您正在使用二次二维 (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)
调用进程可以使用所有内存吗?
当您将最后一个数字(当 i == num_PL - 1
和 j == num_PL - 1
时)读入 &rede_conexoes[i][j]
时,您已将 space 分配给 bool
(通常1 字节),但您已要求运行时读取 int
(通常为 4 字节,有时为 8 字节)。这可能会在您分配的 space 末尾写入几个字节。这会导致未定义的行为,从而导致程序看似正常工作、行为异常或崩溃。
根据 num_PL
的值以及您的运行时处理内存管理的方式,这些额外的几个字节可能会覆盖运行时用来跟踪内存块的一些控制数据。根据被覆盖的内容和使用方式,这可能会导致您遇到崩溃。
如评论中所述,一种解决方案是将整数读入 int
类型的局部变量,然后将其分配给 bool
数组。