为什么使用以下代码获得“双重释放或腐败”?

时间:2018-09-28 22:00:13

标签: c cs50

我正在编写一个简单的程序,以确保当我通过哈佛的CS50时能完全理解C中的指针如何工作。这是代码:

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

int main(void)
{
    int *a = malloc(sizeof(int));
    *a = 5;
    printf("the address of pointer a is: %p\n", &a);
    printf("the address that a is pointing to is: %p\n", a);
    printf("the contents of a are: %i\n", *a);

    printf("please enter a new value for a: \n");
    scanf("%i", a);
    printf("the address of pointer a is: %p\n", &a);
    printf("the address that a is pointing to is: %p\n", a);
    printf("the contents of a are: %i\n", *a);

    int *b = malloc(sizeof(int));
    *b = 7;
    printf("the address of pointer b is: %p\n", &b);
    printf("the address that b is pointing to is: %p\n", b);
    printf("the contents of b are: %i\n", *b);

    a = b;
    printf("setting a = b\n");
    printf("the address of pointer a is: %p\n", &a);
    printf("the address that a is pointing to is: %p\n", a);
    printf("the contents of a are: %i\n", *a);

    free(a);
    free(b);
}

它编译没有问题,但是执行时,出现以下错误:“ *`./address'中的错误:双重释放或损坏(fasttop):0x00000000018b7030 * 中止了”

如果我摆脱了free(a)或free(b)语句,这个问题就解决了,但是valgrind揭示了内存泄漏: “ == 9626 == 1块中的4个字节肯定在1的丢失记录中丢失 == 9626 == at 0x4C2AB80:malloc(在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) == 9626 ==通过0x4206AD:main(address.c:6)“

我浏览了这里的其他问题以及其他提到双重免费腐败的网站,但仍然无法弄清楚问题出在什么地方……我觉得答案很简单,问题很可能是在于语句“ a = b”中,但是我真的不明白为什么我无法让一个指针指向另一个指针指向的内存位置,然后释放两个指针占用的内存。 ..

3 个答案:

答案 0 :(得分:5)

您正在这样做:

 a = b; // a now points to the same thing as b does

...

free(a);
free(b);

...在语义上等同于

free(b);
free(b);

这是双倍的免费-b获得两次免费-这在C中是不允许的。


对于您的内存泄漏问题:

设置a = b时,将丢失a的原始值。 a是指向您丢失的int *a = malloc(sizeof(int));分配的内存的指针。如果要让valgrind停止抱怨泄漏,则需要保存该地址并将其传递给free()。​​

对于malloc()返回的每个地址(零... ^ _ ^除外),您应该使用与参数完全相同的地址调用free()

答案 1 :(得分:3)

让我们将代码减少到最低限度:

#include <stdlib.h>

int main(void)
{
    int *a = malloc(sizeof(int));
    int *b = malloc(sizeof(int));

    a = b; // after the assignment the pointer value previously held by a is gone.
           // both pointers point to the same memory. The memory previously pointed
           // to by a can no longer be free()d since its address is gone.

    free(a); // free the memory pointed to by b (a is a copy of b) once
    free(b); // free the memory pointed to by b twice --> boom.
}

答案 2 :(得分:0)

执行此操作时:

 a = b;

您实际上使ab指向相同的地址(也就是相同的指针)。所以这是导致错误的原因:

free(a); // Frees the location where b points to
free(b);