2011-11-09 194 views
0
char* x = malloc(512); 
memset(x, 0, 513); 
free(x); 

這是爲什麼這個程序崩潰?這是說free(): invalid pointer: 0x0000000000614010 這沒有任何意義,如果有的話它應該破壞程序的一些其他隨機部分,因爲它寫入未定義的內存空間。爲什麼這個指針無效?

+2

[鼻惡魔](http://catb.org/jargon/html/N/nasal-demons.html)! – ephemient

回答

14

你已經導致了未定義的行爲,所以什麼都可能發生。在這種情況下,您的free()實現可能會在緩衝區之後立即檢查空間中的某些信息。既然你把它覆蓋了,那就是遊戲結束了。

+4

+1遊戲結束 – orlp

+0

@Carl哦上帝,這是討厭的。我一直認爲「未定義」的意思是:「可能會有一些崩潰」。看起來供應商只是在這些場合實施隨機的東西!很有幫助的實現。 – Blub

+4

@Blub:Eehm,__no__。你寧願錯誤'免費():無效指針:0x0000000000614010'或BSOD?究竟。你應該很高興你甚至收到錯誤信息。 – orlp

0

您已經分配了512字節的內存,但正在向其寫入513個字節。 free()大概是檢查內存區域是否仍然有效(如果它包含您寫過的保護字節,則不會)。

2

你是malloc ing 512字節,而你正在用memset寫入513字節,所以你已經損壞了堆。

如果它不是很明顯,它是未定義的行爲。你因爲溢出堆而寫了一個用於管理堆結構的重要地址。

+0

-1,這個答案與_「你正在給x添加1」很有用_對包含_「x + = 1」_的問題很有用。 – orlp

+0

@nightcracker:這個答案很好;含義是「你在調用未定義的行爲」。其他可能的解釋只是猜測。 –

+0

@nightcracker我可以明確說明你正在導致未定義的行爲,但我認爲這很明顯。無論如何,我直接閱讀這個問題,原因是因爲他通過寫入太多字節來破壞堆。 – AusCBloke

3

我是新來的,但我希望我能回答這個問題,讓您滿意。

您正在通過覆蓋分配的塊的重要部分來激發未定義的行爲。您正在刪除該塊上大小信息的第一個(高位字節),即由malloc編寫。大多數C標準庫使用Doug Lea Malloc追加和prepends一些字節到您的塊,它們包含大小和使用信息。通過覆蓋這個,你實際上銷燬了free()調用成功所需的信息,並真正釋放了malloc的內存。 malloc的某些實現不會這樣做,併爲塊對齊和大小保留一個「帶外」表(其他位置,而不覆蓋它),並且一些只是預先附加/追加該信息。正如我所說,你的程序崩潰,因爲你覆蓋了重要的信息,沒有它,free()就是不能做它應該做的事情。

0

堆分配器在分配內存之前和/或之後立即放置一些簿記信息是很常見的。你觀察到的一個可能的解釋是你已經覆蓋了對內存分配器的操作至關重要的一些數據,可能是分配的塊的大小或下一個可用空間的位置。

在任何情況下,在您分配的空間範圍之外寫入都是未定義的行爲,並且可能發生任何事情。僅僅因爲這是現在發生的事情並不意味着它會發生在不同的系統上,甚至在不同的時間在同一個系統上。相反,即使你沒有看到錯誤,這並不意味着未定義的行爲不會被調用。這是使用不安全語言的成本,例如C.