提问人:Daniel 提问时间:11/5/2023 最后编辑:Daniel 更新时间:11/5/2023 访问量:128
C malloc 有效,但不应该
C malloc works, but it should not
问:
对于我的线性代数代码,我需要为较低的三角矩阵分配内存,
由一维数组表示。我正在试验我可以分配多少元素和
偶然发现了一个奇怪的行为。如果我设置为高于 的任何内容,则失败并且我的机器无法分配足够的内存,但将其设置为 不会失败,并且
我的代码稍后在循环中崩溃,在大约迭代后初始化数组(超出
边界索引被排除在外,因为可能的错误源)。有人知道这里发生了什么吗?double bottom_row_final
240.0
malloc
410.0
malloc
for
30
//array.c
#include <stdio.h>
#include <stdlib.h>
void vector_alloc(int N, double **pM) {
if ((*pM = (double *)malloc(N * sizeof(double))) == NULL) {
printf("Error: malloc failed!\n");
exit(0);
}
}
void vector_free(double **pM) {
free(*pM);
*pM = NULL;
}
int main(void) {
//-----------------------------------------------------------------------------------------------------------------------
double grid_step = 0.0125;
double bottom_row_final = 410.0; // 230 works, 240 and above does not allocate anymore, but 410 does
int bottom_row_elements = (int)(bottom_row_final / grid_step) + 1;
int lower_triangular_matrix_elements = bottom_row_elements * (bottom_row_elements + 1) / 2;
double *matrix;
vector_alloc(lower_triangular_matrix_elements, &matrix);
int index_jumper = 0;
//-----------------------------------------------------------------------------------------------------------------------
for (int i = 0; i <= bottom_row_elements; i++) {
if (i < bottom_row_elements) {
printf("\n%d\t%d", index_jumper, lower_triangular_matrix_elements - 1);
matrix[index_jumper] = 1.0;
printf("\tInitialized with value");
index_jumper += (bottom_row_elements - i);
}
}
//-----------------------------------------------------------------------------------------------------------------------
vector_free(&matrix);
}
我尝试调试代码,但出现分段错误(显然),但不应该
甚至能够为上述分配内存。malloc
double bottom_row_final
240.0
答:
-1赞
Ken
11/5/2023
#1
我尝试复制您的问题,但我不能。你确定malloc()真的有效吗?您是否收到错误消息,在没有调试的情况下运行它?
评论
0赞
Daniel
11/5/2023
对不起,没有指定,如果 malloc 失败并退出,我的数组分配函数会打印错误。在这种情况下,将双bottom_row_final设置为 410.0,我的代码继续运行,稍后在 for 循环中崩溃。
1赞
Eric Postpischil
11/5/2023
这不是问题的答案。当您有足够的声誉时,您将能够对问题发表评论。您应该避免发表评论或问题作为答案。
3赞
chqrlie
11/5/2023
#2
问题就在这里:
int lower_triangular_matrix_elements = bottom_row_elements * (bottom_row_elements + 1) / 2;
当大于 时,乘法会导致有符号的算术溢出,该溢出具有未定义的行为。根据实际值,结果可能是负数或正数,导致请求因请求太大而失败,或者导致成功但内存量低于所需内存量,从而在访问超出分配大小末尾时导致进一步的未定义行为。bottom_row_elements
46340
malloc()
您应该使用 for the computations,而不是 .size_t
int
//array.c
#include <stdio.h>
#include <stdlib.h>
void vector_alloc(size_t N, double **pM) {
// Allocate the array, initialized to 0.0, assuming IEEE 754 doubles
if ((*pM = (double *)calloc(N, sizeof(double))) == NULL) {
printf("Fehler: malloc fehlgeschlagen!\n");
exit(0);
}
}
void vector_free(double **pM) {
free(*pM);
*pM = NULL;
}
int main(void) {
//-----------------------------------------------------------------------------------------------------------------------
double grid_step = 0.0125;
double bottom_row_final = 410.0;
size_t bottom_row_elements = (size_t)(bottom_row_final / grid_step) + 1;
size_t lower_triangular_matrix_elements = bottom_row_elements * (bottom_row_elements + 1) / 2;
double *matrix = NULL;
vector_alloc(lower_triangular_matrix_elements, &matrix);
size_t index_jumper = 0;
//-----------------------------------------------------------------------------------------------------------------------
for (size_t i = 0; i < bottom_row_elements; i++) {
printf("\n%zu\t%zu",
index_jumper, lower_triangular_matrix_elements - 1);
matrix[index_jumper] = 1.0;
printf("\tInitialized with value");
index_jumper += bottom_row_elements - i;
}
//-----------------------------------------------------------------------------------------------------------------------
vector_free(&matrix);
}
评论
0赞
Daniel
11/5/2023
嗨,感谢您的编辑,使我的问题更加简洁,当然还有答案。我尝试使用 size_t,但 malloc 仍然设法分配内存,即使它不应该。也许我应该提一下,我在 Windows 上并使用 MinGW 的 gcc 端口。
0赞
chqrlie
11/5/2023
尝试上面修改后的版本:比 Windows 64 位大得多,并且必须用于所有大小和索引变量。您应该能够分配 537,936,400 个双精度的数组,即 4.3GB,除非您的系统阻止如此大的块。size_t
int
0赞
Daniel
11/5/2023
您好,谢谢。我尝试使用 size_t但 malloc 仍然分配,即使它不应该。从 malloc 切换到 calloc 使其不再分配,这很好,但是为什么 malloc 仍然分配这个特定数字,当限制远远超过限制时?
0赞
chqrlie
11/5/2023
@Daniel:并且应该表现得一样。你确定这些论点吗?我曾经免费获得零初始化。根据操作系统的不同,数组可能会被分配为具有许多共享页面的稀疏数组。4.3 GB 不一定是这么大的数字,我的笔记本电脑有 24 GB,我可以毫不费力地分配 4.3 GB。calloc
malloc
calloc()
0赞
Daniel
11/5/2023
嗨,我同意,它们的行为应该相同,并且它们对 240.0 以上的每个数字bottom_row_final都是这样做的。但是对于 410.0 calloc 失败,并且 malloc 通过,即使我使用的是 size_t。我的系统只有 8 GB,我需要关闭所有程序,以便我的代码可以分配 4.3GB。这真的很神秘。
评论
if( (*pm = ...) == NULL ) { perror("malloc"); exit(1); }
exit(EXIT_FAILURE);
)