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

时间:2018-04-07 21:57:24

标签: c pointers memory malloc free

我意识到已经多次询问过,但没有一个解决方案能为我提供任何帮助。我正在编写一个实验室程序,在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] = "\0";
/*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);

然而,我得到了恐惧&#34;无效指针&#34;错误。如果有人对如何解决这个问题有任何建议或了解,请分享。

1 个答案:

答案 0 :(得分:2)

您展示的程序片段会出现许多问题,其中一些问题已在评论中确定:

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

但是,主要问题是问题中的代码使用*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], '\0', 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秒。它每次生成的总和是相同的,因为代码不会为随机数生成器播种。