free()如何运作?

时间:2011-08-10 07:16:41

标签: c

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

4 个答案:

答案 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