#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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()做什么。?
它只是将所有内存都设为0 .. ??
答案 0 :(得分:4)
自由静止指针保存该内存的地址后,为什么我们无法打印该内存的值。??
因为记忆不再属于你。你free
它,这意味着允许操作系统重用它,不管它需要分配更多内存。您不再拥有它,因此您不再需要任何业务来查看该内存所拥有的数据的值。
另请注意:
int *ptr;
...
printf("Before malloc valu is :%d\n", *ptr);
同样无效。 ptr
包含垃圾值,可以指向任何位置。取消引用它不能保证是您可以访问的内存位置。
这两种情况都会调用未定义的行为,这意味着标准会说“不要这样做”,如果你忽略了标准,那么只要你的老板看起来,你的代码就会以可怕的方式破解
free()做什么。?
它只是将所有内存都设为0 .. ??
不,不一定。操作系统通常会在后台将未使用的内存清零,以便更快地调用calloc
,但free
只告诉操作系统“我已经完成了这个内存,无论你需要做什么。”操作系统通常会更新一些内务处理数据,以指示内存块不再由进程拥有,以便稍后调用malloc
可以在需要时使用它。
答案 1 :(得分:3)
free
将内存返回给系统。它是malloc
的合作伙伴操作。使用malloc
分配的所有内存块都应通过调用free
返回给系统。致电free
后,您不再被允许访问该内存。
通常认为在调用NULL
之后将指针设置为free
是明智的,至少在调试版本中,以便您可以确定如果稍后尝试将引发错误错误地取消引用指针。
那么,为什么你仍然可以访问已被释放的内存?好吧,你不能可靠地这样做。事实上,大多数内存管理系统的实现意味着您有时可以摆脱这种滥用。许多内存管理器从操作系统分配大块内存,然后又为应用程序分配小的子块。当您调用free
时,分配器将该块返回到其可用内存池,但不一定将内存返回给OS,因为OS内存分配例程通常很昂贵。因此,访问它可能仍然有效,因为内存仍然在您的进程中分配。它只是由内存管理器而不是你的应用程序拥有。这样的事情发生在你身上。
当然,有时你不会逃避这样的滥用行为,很可能是你将软件部署到最重要的客户机器上之后!
答案 2 :(得分:3)
关于malloc()
和free()
的有趣之处在于它们实际上并没有改变它们给你的记忆 - 它们只是改变了它的“思想”。
当您调用malloc()时,会选择一段内存并专用于您的内存。虽然它是你的,你可以按照自己喜欢的方式使用它。
当你完成它时free()
它 - 但它仍然在那里。它仍然是相同的记忆[1],它不再被认为是“你的”了。所以其他人可能正在使用它。
[1]我认为虚拟寻址可能并非总是如此。但通常都是如此。
答案 3 :(得分:1)
通常情况下,内存管理器会有类似用于满足后续分配的空闲块链表。
这是我几年前写的最小实现。它并不是真正意图(或适合)用于严肃使用,但至少提供了一种管理堆的方法的一般概念:
#include <stddef.h>
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)
size = new_size;
size -= sizeof(size_t);
if ( b->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<size;i++)
temp[i] = ((char *)block)[i];
b_free(block);
return temp;
}
#ifdef TEST
#define num 10
int main(void) {
int i;
char block[4096];
char *temp[num];
char *big;
b_init(block, sizeof(block));
big = b_malloc(100);
for (i=0; i<num; i++)
temp[i] = b_malloc(10);
for (i=0; i<num; i++)
b_free(temp[i]);
b_realloc(big, 200);
b_realloc(big, 10);
b_realloc(big, 0);
return 0;
}
#endif