2011-08-10 46 views
1
#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; 
} 

輸出爲:free()如何工作?

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

在printf的,你取消對NULL指針「之前的malloc VALU」。不要這樣做。 –

+0

聲明任何指針後不指向NULL ...那麼它的安全..不是.. .. ?? ?? –

+1

不,它並不總是安全的,因爲它不是標準化的,加上,當它的NULL也不應該遵守它。它會導致任何體面系統上的seg故障。並且,請不要在未來使用大寫鎖定。 –

回答

4

自由靜態指針後保存該內存的地址,爲什麼我們不能打印該內存的值。

因爲內存不再屬於你。這意味着操作系統可以重用它,但它看起來合適,無論它需要分配更多的內存。您不再擁有它,因此您不再有任何業務來查看該內存所擁有的數據的價值。

還要注意的是:

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

同樣無效。 ptr包含垃圾值,可以指向任何地方。解除引用不一定是您可以訪問的內存位置。

這些案件都援引未定義行爲,這意味着標準的說,「不這樣做,」如果你忽略了你的標準代碼將在可怕的方式劃分,每當你的老闆看。

free()做了什麼?

它只是使所有內存爲0 .. ??

不,不一定。操作系統通常會在後臺清空未使用的內存以更快地調用calloc,但free僅告訴操作系統「我已完成此內存,可以隨時隨地使用它」。操作系統通常會更新一些內務處理數據,以指示內存塊不再由進程擁有,因此如果需要,稍後的malloc調用可以使用它。

+0

哇...你已經解釋了一切......想想你 –

+0

在任何情況下,我還能夠訪問我已釋放的那些內存。 –

+1

@ Mr.32 - 否。釋放後訪問內存是未定義的行爲。如果你這樣做,編譯器在法律上允許你的代碼做任何事情(通常的笑話是鼻惡魔:[http://www.catb.org/jargon/html/N/nasal-demons.html])。 –

3

free將內存返回給系統。這是malloc的合作伙伴操作。應通過調用free將您分配的所有內存塊與malloc一起返回給系統。在您致電free後,您不再可以訪問該內存。

它通常被認爲是明智的指針設置爲NULL你叫free後,至少在調試版本,這樣就可以確保一個錯誤將引發如果以後嘗試取消引用指針錯誤。


那麼,爲什麼你還能訪問已經被釋放的內存?那麼,你不能可靠地這樣做。實際上,大多數內存管理系統的實現意味着你有時可以逃避這種濫用。許多內存管理器從操作系統分配大塊內存,然後將小的子塊分配給應用程序。當您調用free時,分配器會將該塊返回到其可用內存池,但不一定會將該內存返回給操作系統,因爲操作系統內存分配例程通常很昂貴。因此訪問它可能仍然有效,因爲內存仍然在您的進程中分配。只是它現在由內存管理員擁有,而不是由您的應用程序擁有。像這樣的事情在這裏發生在你身上。

當然,有時你不會逃避這樣的濫用,很可能一旦你將你的軟件部署到你最重要的客戶端機器上!

+0

當我們malloc的東西..實際上這個內存戈納reseve。在堆棧..?在堆..?在Ram .. ?? –

+0

@Mr。 32這是特定實現,但在大多數系統中,malloc分配堆內存。 –

+0

RAM上的堆棧和堆。 Malloc應該保留在堆空間中,所以它在函數結束時不會被刪除。 –

3

關於malloc()free()有趣的是他們並沒有改變他們給你的記憶 - 他們只是改變它的「想法」。

當您調用malloc()時,會選擇一段內存並將其專用爲您的內存。雖然它是你的,你可以使用它你喜歡的方式。

當你完成它,你free()它 - 但它仍然存在。它仍然是相同的記憶[1],它不再被認爲是「你的」。所以別人可能會使用它。

[1]我認爲虛擬尋址可能並非總是如此。但通常是這樣。

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