为什么在使用malloc()后两个内存位置会发生改变&;free()?

为什么在使用malloc()后两个内存位置会发生改变&;free()?,c,pointers,visual-c++,memory-management,malloc,C,Pointers,Visual C++,Memory Management,Malloc,在下面的代码中,我为几个int指针分配内存,设置它们的数据,打印数据信息,并释放它们。然后,我为一个新的int指针分配数据,并再次打印所有数据 我观察到的是,相同的数据被写入内存中的新位置以及以前释放的位置之一。我希望它能写到一个以前免费的位置,但为什么它还要写到一个新的位置呢 顺便说一下,我在MS Visual C++ 2010中工作。p> 代码如下: #include <stdio.h> #include <stdlib.h> int main(int argc,

在下面的代码中,我为几个int指针分配内存,设置它们的数据,打印数据信息,并释放它们。然后,我为一个新的int指针分配数据,并再次打印所有数据

我观察到的是,相同的数据被写入内存中的新位置以及以前释放的位置之一。我希望它能写到一个以前免费的位置,但为什么它还要写到一个新的位置呢

顺便说一下,我在MS Visual C++ 2010中工作。p> 代码如下:

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

int main(int argc, char *argv)
{
    int *ip;
    int *jp;
    int *xp;

    printf("\n   Memory Allocation Test Bench\n")
    printf("----------------------------------\n");

    ip = malloc(sizeof(*ip));
    jp = malloc(sizeof(void *));

    *ip = 10;
    *jp = 20;

    printf("ip Data: %d, Location: %p\n", *ip, &ip);
    printf("jp Data: %d, Location: %p\n", *jp, &jp);

    free(ip);
    free(jp);

    xp = malloc(sizeof(*xp));

    *xp = 40;

    printf("\nAfter freeing all and setting *xp = 40...\n");
    printf("ip Data: %d, Location: %p\n", *ip, &ip);
    printf("jp Data: %d, Location: %p\n", *jp, &jp);
    printf("xp Data: %d, Location: %p\n", *xp, &xp);

    free(xp);

    printf("\nAfter freeing xp...\n");
    printf("ip Data: %d, Location: %p\n", *ip, &ip);
    printf("jp Data: %d, Location: %p\n", *jp, &jp);
    printf("xp Data: %d, Location: %p\n", *xp, &xp);

    printf("\nPress any key to continue... \n");
    getchar();

    return EXIT_SUCCESS;
} // End of Main
用这样的句子:

printf("xp Data: %d, Location: %p\n", *xp, &xp);
printf("xp Data: %d, Location: %p\n", *xp, xp);
生成了这个新的输出,它清楚地显示了一切都正常工作。最后一个malloc()语句回收了以前释放的内存。由于从技术上讲,释放的指针仍然指向内存中的有效位置,因此看起来有两个位置同时被更改:

撇开未定义的行为不谈,这一解释至少为正在发生的事情提供了理由——一个非常简单的(和业余的)编码错误。这个故事的寓意是:记下您正在谈论的地址(堆与堆栈),不要试图使用释放的指针访问内存。

没有“两个内存位置被改变”。我想你说的是输出线:

ip Data: 40, Location: 0012FF60
xp Data: 40, Location: 0012FF3C
但是,您的“位置”不是存储
40
的位置;它是指针
ip
xp
的位置(在堆栈上)。要查看
40
的存储位置,请输出
xp
,而不是
&xp

此外,还应将与
%p
格式说明符匹配的参数强制转换为
(void*)


尝试打印已释放指针的值是未定义的行为,更不用说取消引用它了(
ip
*ip
)。要可靠地打印
ip
,请在
释放
它之前执行该操作。

程序中有多个未定义的行为调用。不存在数据复制之类的事情。如果在调试器中遍历代码,单步遍历程序集,则可以解释正在发生的情况。但最基本的事实是,当你释放一个缓冲区时,你不应该再使用它,因为读取是不可靠的,而写入会导致严重的问题。在UB中,逻辑也是错误的。您正在打印的“位置”是本地变量的地址,与动态分配返回的地址无关(如前所述,随后释放并取消对trip UB的引用)。在那里传递的值应该是返回的地址,而不是保存这些地址的指针的地址。例如:
printf(“ip数据:%d,位置:%p\n”,*ip,ip)使用已被
释放的指针是未定义的行为
d;@KurtE.Clothier:您显然没有意识到“未定义行为”是对C标准的引用,并且一旦您的程序包含UB,该标准允许它做任何事情,包括重新格式化硬盘、重新启动计算机等。在释放指向UB的指针后,使用指针。你接受的答案不是一个好答案,因为它忽略了UB。当您更多地使用SO时,您可能会理解为什么一些老手会这样评论。在“更新”版本中,您会注意到“匹配”值都位于同一地址,例如,您多次输出同一地址的内容。您的示例显示,当您
空闲
内存和
malloc
更多内存时,新分配的内存可能与之前的
空闲
内存位于同一位置。