struct element {
unsigned long int ip;
int type;
int rtt;
struct element * next;
struct element * edge;
};
我有一个链表。我使用malloc创建新节点。 我尝试使用free(ptr to node)释放内存 但是当我再次运行遍历函数时,我可以遍历链表并且rtt值是正确的,以及下一个和边指针,因为我可以跟随链表。只有ip值被破坏了。这是为什么?
答案 0 :(得分:7)
malloc()
和free()
的行为在很大程度上取决于您使用的操作系统和C库。在大多数实现中,实际上有两个内存分配器在起作用:
操作系统内存分配器,它使用处理器的虚拟内存功能为进程提供自己的地址空间,并将物理内存页面映射到该地址空间以供使用。
C库内存分配器,实际上是应用程序代码的一部分,使用操作系统提供的页面提供细粒度的内存管理工具,由malloc()
和{{1提供}}
通常,调用free()
会执行以下一项或多项操作:
它在C内存分配器中将指向的内存区域标记为空闲。这允许重用该内存。 free()
不会将释放的内存清零。
它可能将内存返回给操作系统,具体取决于C内存分配器的设置以及是否实际可以释放堆的那部分内容。如果内存未返回给操作系统,则同一应用程序将来的free()
调用可以重用该内存。
如果您尝试访问已释放的内存,通常会发生以下三种情况之一:
内存已经返回到操作系统,您的程序通常会崩溃。如果你问我,这可能是最好的情况 - 你有问题,当然,但你知道吗。
内存未被重用,因此您的旧数据仍然存在。你的程序继续,好像什么都没有错。这是我认为最糟糕的情况。你的代码似乎工作正常,如果墨菲有发言权,它将继续这样做,直到它到达你的最终用户 - 然后它将会失败。
您的程序已经重用了内存,您的代码将开始乱搞自己的数据。如果你小心(幸运吗?),你可能会注意到结果是关闭的。如果没有,那么......
如果您使用Linux / Unix Valgrind是一个很好的工具来捕获这样的内存管理问题。还有用于C内存分配器的替换库,例如DUMA,它还允许您检测此类问题。
答案 1 :(得分:1)
实际上free不会删除任何内容,它只是告诉操作系统它可以再次使用该内存,例如下次调用malloc()时它可以覆盖你的一些节点。
答案 2 :(得分:1)
释放内存会释放它以供重用。它不一定会破坏该位置的数据。由于行为未定义(即通常非常糟糕),因此您不能访问已释放的内存区域。
如果您因某些奇怪的原因需要销毁数据,请在释放之前覆盖内存区域(例如memset(buf, 0, len)
)。
答案 3 :(得分:1)
释放内存时不会擦除内存 - 这会浪费处理器时间。它只是分配给“免费列表”。这就是为什么你的数据还在那里
每当你释放一个块时,你应该将相应的指针设置为NULL,这样你就不会意外地引用它 - 它可以在任何时候重复使用。