free()如何运作?

#include  #include  #include  int main () { int * ptr; printf("before malloc pointer is :%p \n",ptr); printf("before malloc valu is :%d \n",*ptr); ptr = malloc(sizeof(int)); printf("after malloc pointer is %p \n",ptr); printf("after malloc valu is :%d \n",*ptr); int jig=32; *ptr = jig; printf("after assignment valu is : %d\n",*ptr); free(ptr); printf("after free %p \n",ptr); // after free pointer holds sane address then printf("after fee is %d\n",*ptr); // why it coudnt print that??? return 0; } 

输出是:

  before malloc pointer is :0x6edff4 before malloc valu is :7265660 after malloc pointer is 0x9a52008 after malloc valu is :0 after assignment valu is : 32 after free 0x9a52008 after fee is 0 

在free仍然指针保存该内存的地址之后,为什么我们无法打印该内存的值。

free()做什么。

它只是使所有内存为0 .. ??

在free仍然指针保存该内存的地址之后,为什么我们无法打印该内存的值。

因为记忆不再属于你。 你free它,这意味着允许操作系统重用它,但它认为合适,无论它需要分配更多的内存。 您不再拥有它,因此您不再需要任何业务来查看该内存所拥有的数据的值。

还要注意:

 int *ptr; ... printf("Before malloc valu is :%d\n", *ptr); 

同样无效。 ptr持有垃圾值,可以指向任何地方。 取消引用它不能保证是您可以访问的内存位置。

这两种情况都会调用未定义的行为 ,这意味着标准说“不要这样做”,如果你忽略了标准,你的代码会在老板看的时候以可怕的方式破解。

free()做什么。

它只是使所有内存为0 .. ??

不,不一定。 操作系统通常会在后台将未使用的内存calloc ,以便更快地调用calloc ,但free只告诉操作系统“我已经完成了这个内存,无论你需要做什么”。 操作系统通常会更新一些内务处理数据,以指示内存块不再由进程拥有,因此稍后调用malloc可以在需要时使用它。

关于malloc()free()的有趣之处在于它们实际上并没有改变它们给你的内存 – 它们只是改变了它的“思想”。

当您调用malloc()时,会选择一段内存并专用于您的内存。 虽然它是你的,你可以按照自己喜欢的方式使用它。

当你完成它之后,你将它free()它 – 但它仍然存在。 它仍然是相同的记忆[1],它不再被认为是“你的”了。 所以其他人可能正在使用它。

[1]我认为虚拟寻址可能并非总是如此。 但这通常是正确的。

free将内存返回给系统。 它是malloc的合作伙伴。 使用malloc分配的所有内存块都应该通过free调用返回给系统。 在您free拨打电话后,您将不再被允许访问该内存。

在调用free之后将指针设置为NULL通常被认为是明智的,至少在调试版本中是这样,这样如果以后尝试错误地取消引用指针,就可以确保会引发错误。


那么,为什么你仍然可以访问已被释放的内存? 好吧,你不能可靠地这样做。 事实上,大多数内存管理系统的实现意味着您有时可以摆脱这种滥用。 许多内存管理器从操作系统分配大块内存,然后又将小块子分配给应用程序。 当您调用free ,分配器将该块返回到其可用内存池,但不一定将内存返回给OS,因为OS内存分配例程通常很昂贵。 因此,访问它可能仍然有效,因为内存仍然在您的进程中分配。 它只是由内存管理器而不是你的应用程序拥有。 这样的事情发生在你身上。

当然,有时你不会逃避这样的滥用,很可能一旦你将软件部署到最重要的客户机器上!

通常,内存管理器将具有类似于用于满足后续分配的空闲块的链接列表。

这是几年前我写的最小实现。 它并不是真正意图(或适合)严肃使用,但至少给出了一种管理堆的方法的一般概念:

 #include  typedef struct node { size_t size; struct node *next; } node; node *free_list; static void *split_end(node *block, size_t new_size) { size_t difference = block->size - new_size; node *temp = (node *)((char *)block + difference); temp->size = new_size; block->size = difference; return (void *)((size_t *)temp+1); } static void *split_begin(node *block, size_t new_size) { size_t difference = block->size-new_size; node *temp = (node *)((char *)block + new_size); temp->size = difference; temp->next = free_list; free_list = temp; return block; } void b_init(void *block, size_t block_size) { ((node *)block)->size = block_size - sizeof(node); ((node *)block)->next = NULL; free_list = block; } void b_free(void *block) { node *b = (node *)((size_t *)block -1); b->next = free_list; free_list = b; } void *b_malloc(size_t size) { node *temp, **ptr; size_t larger = size+sizeof(node); size += sizeof(size_t); for ( ptr = &free_list; NULL != ptr; ptr = &((*ptr)->next)) { if ((*ptr)->size >= size) { if ( (*ptr)->size <= larger) { temp = (*ptr); (*ptr) = (*ptr)->next; return (void *)((size_t *)temp + 1); } else return split_end(*ptr, size); } } return NULL; } void *b_realloc(void *block, size_t new_size) { node *b = (node *)((char *)block - sizeof(size_t)); char *temp; size_t i, size; if ( new_size == 0) { b_free(block); return NULL; } new_size += sizeof(size_t); size = b->size; if ( new_size size >= new_size+sizeof(node *) ) return split_begin(b, new_size); if ( b->size >= new_size) return b; temp = b_malloc(new_size); if ( NULL == temp) return NULL; for ( i=0; i