C中释放内存后的堆损坏

C中释放内存后的堆损坏,c,visual-c++,heap-memory,C,Visual C++,Heap Memory,我有以下代码: #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

我有以下代码:

#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
}
#包括
#包括
#包括
#ifdef_WIN32
#包括
#elif定义的uu unix__
#包括
#恩迪夫
#定义工作台
#ifndef工作台
#定义N 10000
#恩迪夫
内部主(空)
{
#ifdef工作台
文件*output=fopen(“out.csv”,“w”);

对于(int N=10000;N问题最终位于循环
的终止条件中对于(int j=i;j)循环条件
j以多种N尺寸进行测试(10^3,10^4,10^5,10^6).对于上述循环条件,让我们做一个完整的练习,假设
N=10000
i=2
。然后
N/i
将是
5000
。使用
j
的循环从
2
5000
。当
j=2
然后
i*j
4
。当
j=3
时,
i*j
6
。等等,直到
j==N/i
(即
j==5000
)。现在乘法
i*j
将是
10000
。这超出了
10000
元素数组的范围(请记住,数组索引是从零开始的,因此
N
元素数组的索引范围为
0
N-1
(包括))。值得注意的是,如果未定义BENCH,则不会
释放
数组。我猜您确实超出了数组边界,而VS编译器只会在
释放
上进行检查。因此,如果没有BENCH被污染,则仍然存在内存损坏,没有人注意到:)C没有任何类型的边界检查。一些独立的静态分析器程序可能能够检测到这个问题,但这是一个昂贵的操作,属于未定义行为的领域,因此编译器不必发出警告。