gpt4 book ai didi

c - C 中释放内存后堆损坏

转载 作者:行者123 更新时间:2023-11-30 16:10:55 25 4
gpt4 key购买 nike

我有以下代码:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#ifdef _WIN32
#include <windows.h>
#elif defined __unix__
#include <unistd.h>
#endif

#define BENCH

#ifndef BENCH
#define N 10000
#endif

int main(void)
{
#ifdef BENCH
FILE* output = fopen("out.csv", "w");
for (int N = 10000; N <= 100000; N += 10000)
#endif
{
int* a = malloc(N * sizeof(int));
if (a == NULL)
abort();

for (int i = 2; i < N; i++)
a[i] = 1;

#ifdef BENCH
clock_t begin = clock();
#endif

for (int i = 2; i < N; i++)
{
if (a[i])
{
#if defined (BENCH) && defined (_WIN32)
Sleep(1);
#elif defined (BENCH) && defined (__unix__)
sleep(0.001);
#endif
for (int j = i; j <= N / i; j++)
a[i * j] = 0;
}

}

#ifdef BENCH
clock_t end = clock();
double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
fprintf(output, "%d,%f\n",N ,time_spent);
free(a); //This is where the corruption occurs
#else
for (int i = 2; i < N; i++)
{
if (a[i])
printf("%9d ", i);
}
puts("");
#endif
}
#ifdef BENCH
fclose(output);
#endif
}

如果未定义BENCH,程序将采用预定义的 N 并将结果显示在控制台上。未测量算法的性能。

如果定义了 BENCH,则使用 for 循环创建具有不同输入大小(N) 的问题的多个实例。一旦问题的一个实例完成,算法的性能就会记录在 output.csv 文件中。然后,必须释放为该实例的数组分配的内存。

至少根据 Microsoft Visual C++ 编译器在 Visual Studio 2019 上的说法,这是堆损坏发生的地方。有谁知道为什么会发生这种情况? malloc()free() 对我来说似乎都是正确的。如果删除 free(),程序就可以正常工作。

最佳答案

问题最终定位在循环的终止条件for (int j = i; j <= N / i; j++)而不是 free() 。将其更改为 for (int j = i; j < N / i; j++)解决了堆损坏问题。

正如一些程序员家伙在评论中指出的那样,在调试器没有通知我的情况下发生了越界异常。我主要在 Visual Studio 中编写 C# 代码,因此我有一种错觉,如果出现问题,我至少会在发生不良情况的行中收到异常。

事实并非如此,因为 C 没有任何类型的边界检查。未定义的行为在某些情况下倾向于“正常”工作,然后一些无关紧要的事情发生变化,一切都会崩溃。正如 AbbysSoul 指出的那样,在所有情况下都会发生堆损坏,即使是 BENCH 也是如此。不明确的。当像free()这样的关键操作时在损坏的堆上调用,该进程注定会崩溃。

这里的重要教训是检查 C 程序中的所有代码行,尤其是当您在发生异常的行中没有看到任何错误时。

关于c - C 中释放内存后堆损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58778756/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com