簡體   English   中英

動態內存分配功能-Malloc和Free

[英]Dynamic Memory Allocation Functions- Malloc and Free

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
char *p;
p = (char *)malloc(4*sizeof(char));
strcpy(p, "abcdabcd");
printf("%s\n", p);
free(p);
printf("%s\n", p);
return 0;
}

我嘗試在Ubuntu上運行以上代碼。 在這里,我從malloc分配4個字節的內存。 然后,我嘗試將8個字節復制到malloc分配的內存中。 我沒有收到任何警告或錯誤。 我嘗試釋放內存塊,並嘗試使用與釋放相同的內存,但再次沒有任何問題。 它打印了正確的字符串。 有人可以解釋這種行為嗎?

該行為不能得到有意義的解釋。 您的程序表現出未定義的行為,這意味着任何事情都可能發生。 “任何內容”還包括您在實驗中觀察到的行為,即“打印正確的字符串”。

今天,它“打印了正確的字符串”。 明天它可能會崩潰。 后天,它可能會格式化硬盤。 在未定義行為的概念下,這是完全允許的。

在[未定義的行為]類別中,其他正確的操作。

當程序啟動時,可以通過OS訪問虛擬內存。 通常,虛擬頁面具有一些最小大小(例如4 kb),這是處理它們的最小大小。

因此,您需要使用小於該頁面大小的malloc請求內存,並且整個塊都可用。 其他程序可能會使用此塊的部分/無/全部 但是從技術上講,它仍然存在:

1 byte | 1 byte | 1 byte | 1 byte | more memory you don't have....
 ^ char p points here

然后,您開始轉儲,將字符串從p開始復制到內存 這樣就得到:

a | b | c | d | the rest of the chars start dumping into somebody elses space!

此重疊是不確定的。 換句話說,我們可能有未使用的內存,因此今天一切正常。 明天,物理內存空間將由OS占用,我們將無法覆蓋它。 第二天,我們中斷了其他程序。 第二天,我們斷斷續續。

正如其他人指出的那樣,C不會照顧您。

C語言不保證任何內存檢查。 基本上,如果您寫入的內存不是您的內存(例如,您寫入的內存超出了數組的范圍),或者您從不是您的內存中讀取內容(例如,從內存中讀取,則通過釋放它而放棄了它) )不知道會發生什么。

但是,操作系統可能會或可能不會阻止您執行這兩項操作。 通常,如果發生這種情況,則會出現“ Bus Error”或“ Segmentation Fault”錯誤 但是,也不能保證這兩種情況都會發生。

最好的辦法是防御性編碼。 跟蹤陣列的長度,然后斷言或以其他方式檢查復制到陣列中的內容是否不超過陣列的大小。

您可以做的另一件事是調試。 Valgrind是一種非常有效的工具,可用來解決您所描述的問題。 它可以指示兩種情況,即您尚未對內存進行讀或寫操作。 它還可以識別泄漏,例如當您分配內存時,后來又忘記釋放它。

我相信它沿着塊對齊分配,這就是為什么在這種情況下它為您提供了一些神奇的額外內存的原因。 嘗試將其升至更大的字節倍數(例如16,64等),並且應該更加精確,如果超出該范圍,則可能會出現段錯誤。 但是請記住,如果在malloc塊之后的內存也是程序的內存空間的一部分,那么您也不會遇到段錯誤。

通常,只要您留在程序的內存段中,就可以愉快地讀取/寫入所需的所有內容(當然,您自己要承擔:D的風險)。

如果您真的想檢查程序,請在“ / valgrind”中運行

每個說您已調用未定義行為的人都是正確的。

它似乎正常工作的原因可能是平台上堆管理器的特定實現的副作用。 例如,許多內存管理器將分配值舍入到一些方便的大小,而最小大小通常為8或16個字節。 永遠不應依賴此類實現細節。

一些平台具有一些工具,可在您開發程序時嘗試捕獲這些類型的假設。

就像所有其他人所說的那樣,您的代碼會導致未定義的行為(可能發生任何事情)。

釋放后,堆內存分配器(malloc)對存儲在該區域中的數據不承擔任何責任

了解malloc的職責將幫助您解釋為什么看到結果,為什么錯誤的編程習慣以及為什么它不會一直有效。

Malloc是glibc中的堆內存分配器(_int_malloc和_int_free)。 您可以在此處查看其代碼[ http://code.woboq.org/userspace/glibc/malloc/malloc.c.html#_int_malloc]

有人可以解釋這種行為嗎?

一個可笑的例子將有助於快速澄清您的問題。

考慮您正在從一家汽車旅館( sbrk(2) )租用一個房間( 內存 ),而該汽車旅館沒有任何房間的鑰匙( 內存 )!
您去接待員( malloc )要求一個房間( 內存 ),她給您一個可用的房間,您拿走了房間( 內存 )並使用它。
您已完成此操作,現在向她保證您將不再使用它( 釋放 )。 她在書中記下您的房間( 記憶 )是免費的,可以分配給他人。 她希望完全給別人一個房間。
一段時間后,您再次來找您的房間(接待員不檢查您),如果您沒有人在使用房間,您會很幸運(看起來就像您離開時一樣凌亂!)

接待員(malloc)的工作是盡快為您分配一個房間(內存),並相信您在騰空(免費)后會遵守自己的諾言。她的工作並不是防止您使用任何房間(記憶)!

如果您訪問不允許訪問的地方(只讀區域),所有者(內核)就會生氣(例外)。

我是一個新手,我不確定是否適合以這種方式回答。 讓我知道如果我做錯了,我強烈建議您使用malloc

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM