为什么我使用以下代码得到 "double free or corruption"?

Why am I getting "double free or corruption" with the following code?

我正在编写一个简单的程序,以确保我在学习哈佛的 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);
}

它编译 w/o 问题,但在执行时,我收到以下错误:“* `./address' 错误:双重释放或损坏(fasttop):0x00000000018b7030 * 中止

如果我去掉 free(a) 或 free(b) 语句,这个问题就会消失,但是 valgrind 显示内存泄漏: "==9626== 4 bytes in 1 blocks 肯定丢失在 loss record 1 of 1 ==9626== 在 0x4C2AB80:malloc(在 /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so 中) ==9626== by 0x4206AD: main (address.c:6)"

我浏览了这里的其他问题和其他提到双重自由腐败的网站,但仍然无法弄清楚问题是什么......我觉得答案很简单,而且问题可能在于语句 "a = b",但是我真的不明白为什么我不能让一个指针指向另一个指针指向的内存位置,然后释放两者占用的内存指针...

您正在这样做:

 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() returns 的每个地址(零除外...^_^),您应该使用与参数完全相同的地址调用 free()

当你这样做时:

 a = b;

你实际上是在让 ab 指向同一个地址(a.k.a。是同一个指针)。所以这就是导致错误的原因:

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

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

#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.
}