我有一個必須多次呼叫的函式,并且包含我使用 malloc 分配的字串。對該函式的第一次呼叫作業正常,但第二次呼叫似乎從未從記憶體中“洗掉”第一個字串。我一直認為“free”關鍵字意味著它會完全釋放它在堆上分配的記憶體。免費實際上在做什么?
uj5u.com熱心網友回復:
C 2018 7.22.3.3 2 說free(ptr):
該
free函式使 所指向的空間ptr被釋放,也就是說,可用于進一步分配。如果ptr是空指標,則不執行任何操作。否則,如果引數與記憶體管理函式先前回傳的指標不匹配,或者如果空間已通過呼叫freeor被釋放realloc,則行為未定義。
就這些。它使記憶體可用于進一步分配(記憶體管理軟體更新其記錄以記錄記憶體可用于新用途)。不需要改變記憶體(也不需要不改變記憶體),也不會改變ptr(盡管 的“值”ptr在 C 的語意中變得無效)。
uj5u.com熱心網友回復:
C 庫函式void free(void *ptr)取消分配先前通過呼叫 、 或 分配的calloc堆malloc記憶體realloc。
例如:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
size_t my_data_length = 10;
int *my_data = (int *)malloc(sizeof(int) * my_data_length);
for (size_t i = 0; i < my_data_length; i )
my_data[i] = i * i;
for (size_t i = 0; i < my_data_length; i )
printf("%d\n", my_data[i]);
free(my_data);
return 0;
}
上面的代碼生成從 0 到 10 的正方形,10不包括在內。所以,我曾經free取消分配我用來存盤的堆記憶體my_data。
如果我沒有寫free(my_data);,那么輸出也將是相同的,但在后臺會發生一些記憶體泄漏(現代作業系統在程式退出時自行管理記憶體而不釋放其堆分配的記憶體)。
例如:
如果我在 下除錯這段代碼valgrind,輸出將是這樣的:
==29666== HEAP SUMMARY:
==29666== in use at exit: 0 bytes in 0 blocks
==29666== total heap usage: 2 allocs, 2 frees, 4,136 bytes allocated
==29666==
==29666== All heap blocks were freed -- no leaks are possible
==29666==
==29666== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
現在,如果我洗掉該free行,那么valgrind's輸出將是:
==29719== HEAP SUMMARY:
==29719== in use at exit: 40 bytes in 1 blocks
==29719== total heap usage: 2 allocs, 1 frees, 4,136 bytes allocated
==29719==
==29719== Searching for pointers to 1 not-freed blocks
==29719== Checked 114,288 bytes
==29719==
==29719== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
==29719== at 0x4845899: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==29719== by 0x109168: main (main.c:7)
==29719==
==29719== LEAK SUMMARY:
==29719== definitely lost: 40 bytes in 1 blocks
==29719== indirectly lost: 0 bytes in 0 blocks
==29719== possibly lost: 0 bytes in 0 blocks
==29719== still reachable: 0 bytes in 0 blocks
==29719== suppressed: 0 bytes in 0 blocks
==29719==
==29719== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
這清楚地表明退出應用程式時未釋放堆記憶體塊。
uj5u.com熱心網友回復:
當你
malloc在 C 中呼叫 ... 時會發生什么?
讓我們看看沒有 MMU 的計算機(在現代臺式計算機上,它有點復雜):
有一些記憶體區域稱為“堆”。你可以把這個“堆”想象成一個陣列char:
char heap[10000];
該陣列用于 分配的資料malloc。
當您呼叫malloc(200)時,作業系統會檢查當前未使用具有請求大小的陣列中的哪個范圍。假設范圍 from heap[400]toheap[599]當前未使用。
然后作業系統在某處存盤以下資訊:
- 范圍 400...599 不再使用但已使用
- 范圍從
heap[400]200 位元組開始
然后它回傳指標&(heap[400])(這是由回傳的值malloc)。
當你
free(var)在 C 中呼叫 ... 時會發生什么?
比方說var=&(heap[400])。
作業系統讀取的資訊的起始范圍heap[400]為 200 位元組長。(此資訊在 期間存盤malloc。)
然后它存盤范圍 400...599 現在是空閑的資訊,可用于將來呼叫malloc.
...但第二次呼叫似乎從未從記憶體中“洗掉”第一個字串。
作業系統僅存盤了 fromheap[400]到的區域heap[599]未使用的資訊,因此可以在將來呼叫malloc.
malloc除非使用or的特殊安全變體,否則free這 200 個位元組的值不會被覆寫。
并且在你呼叫之后free(var),var仍然會指向heap[400](假設一臺沒有MMU的電腦)!
當您malloc再次以相同大小呼叫時(同時沒有其他程式呼叫malloc過),作業系統很可能會發現范圍 from heap[400]toheap[599]是空閑的并回傳指向heap[400].
并且這個范圍仍然包含您的字串(如果同時沒有呼叫其他程式malloc),因為它沒有被覆寫。
uj5u.com熱心網友回復:
為了回答您的問題, malloc 是記憶體分配的縮寫,因為它正是這樣做的:即使當前沒有使用它,它也會為自己宣告一塊記憶體。這可以確保其他應用程式不會在您的應用程式每次暫停時使用該記憶體。當您分配 1 兆位元組的記憶體時,任務管理器會說您的應用程式正在使用 1 兆位元組的 RAM,即使它根本不使用它分配的記憶體。當您釋放()該記憶體時,它會將其回傳給作業系統以允許其他應用程式使用它。
除了技術方面的東西,聽起來您正在嘗試增加或減少變數可用的 RAM 量。為此,請使用 realloc()。例如:
char *x = malloc(50);
/*
Now your program will determine that you need to reallocate x to a new size.
This could be because the computer has run out of memory, or the
variable you originally planned on placing in x has increased in size.
*/
x = realloc(x, 25);
realloc() 與 free() malloc() 不同,因為它保留了變數的原始值。
在函式中宣告的變數將在該函式結束時自動釋放,同樣,在 if-else、回圈或任何型別的大括號周圍的代碼中宣告的函式也是如此{ }。您可能需要使用 free() 的原因是您需要:
- 釋放程式不再需要的記憶體空間。
- 通過釋放它并再次分配它來將變數重新用于其他用途(這與 realloc() 變數不同,因為 realloc 保留了變數的原始值)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/427879.html
標籤:C
