./thrash 中的错误:free():无效指针

Error in ./thrash: free(): invalid pointer

我知道这个问题已经被问过好几次了,但是 none 的解决方案为我提供了任何帮助。我正在编写一个实验室程序,它在 C 中分配了大量内存,特别是一个 char 指针数组,每个指针都在内存中分配了一个页面的大小,即 4096 字节。

char** pgs =(char**) malloc(sizeof(char *) * pages);
if(pgs == NULL){
    printf("Failed to allocate memory");
    exit(0);
}
int i;
for(i = 0; i < pages; i++){
    pgs[i] = malloc(4096);
    /*if(pgs[i] == NULL){
    printf("Failed to allocate memory");
    exit(0);
    }*/
*pgs[i] = "[=10=]";
/*if(pgs[i] == NULL){
    printf("Failed to allocate memory");
    exit(0);
}*/
}

在程序中间,随机访问和修改此数组的元素以引起抖动(作为实验的一部分):

while(time(NULL) - startTime < seconds){
    long rando = rand() % pages;
    if(modify > 0){
        *pgs[rando]++;
    }
    else{
        long temp = *pgs[rando];
    }

在程序结束时,我尝试释放此内存:

for(i = 0; i < pages; i++){
    free(pgs[i]);
}


free(pgs);

然而,我遇到了可怕的 "invalid pointer" 错误。如果有人对如何修复此问题有任何建议或知识,请分享。

您显示的程序片段存在许多问题,其中一些已在评论中指出:

  • 程序应该在标准错误上报告错误,而不是标准输出。
  • 程序在失败时应以 non-zero 状态退出。
  • 程序应该在没有警告的情况下编译。
  • 一般消息和特定错误消息应以换行符结尾。
  • 程序只尝试修改每一页的一个字节。

但是,主要问题是问题中的代码使用了 *pgs[rando]++,它旨在修改分配的内存。这等同于 *(pgs[rando]++) 递增指针然后读取值并丢弃它 — 而不是等同于 (*pgs[rando])++ 将修改字节 pgs[rando][0]。问题中的代码应该生成关于 value computed is not used 的警告(如果您确保编译时所有警告都被视为错误,则生成错误)。因为您的代码正在递增指针,所以返回给内存分配系统的值 free() 通常与内存分配系统返回给您的值不同,因此您确实传递了无效指针至 free().

这段代码避免了上述问题。它执行固定次数的迭代并且不使用 time()。它打印 sum 以便优化器无法优化对内存的读取访问。

/* SO 4971-2352 */

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

enum { PAGESIZE = 4096 };

int main(void)
{
    int pages = PAGESIZE;
    char **pgs = (char **)malloc(sizeof(char *) * pages);
    if (pgs == NULL)
    {
        fprintf(stderr, "Failed to allocate memory\n");
        exit(EXIT_FAILURE);
    }
    for (int i = 0; i < pages; i++)
    {
        pgs[i] = malloc(PAGESIZE);
        if (pgs[i] == NULL)
        {
            fprintf(stderr, "Failed to allocate memory\n");
            exit(EXIT_FAILURE);
        }
        memset(pgs[i], '[=10=]', PAGESIZE);     // Or use calloc()!
    }

    size_t sum = 0;
    for (int i = 0; i < PAGESIZE * PAGESIZE; i++)
    {
        int pagenum = rand() % pages;
        int offset = rand() % PAGESIZE;
        int modify = i & 2;
        if (modify != 0)
        {
            pgs[pagenum][offset]++;
        }
        else
        {
            sum += pgs[pagenum][offset];
        }
    }

    printf("Sum: 0x%.8zX\n", sum);

    for (int i = 0; i < pages; i++)
        free(pgs[i]);
    free(pgs);

    return 0;
}

我调用了该代码 thrash31.c 并将其编译成 thrash31 使用:

$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror thrash31.c -o thrash31
$

当运行用一个定时程序时,我得到了输出:

$ timecmd -u -- thrash31
2018-04-07 15:48:58.546809 [PID 9178] thrash31
Sum: 0x001FE976
2018-04-07 15:48:59.355508 [PID 9178; status 0x0000]  -  0.808699s
$

因此, 运行 大约用了 0.8 秒。它生成的总和每次都相同,因为代码不会为随机数生成器提供种子。