C語言和C 中,為什麼malloc函式需要傳入申請的記憶體大小,而free時候卻不需要傳大小呢?

時間 2021-05-05 16:23:32

1樓:Hades

前面說書裡面說過,我忙猜,在申請記憶體的時候時間上申請的是乙個資料結構,包含頭部和可以位址資訊,free的時候去資料結構裡找就行了。比如裡要100記憶體,可能實際申請了110的記憶體多的就用來存放一些和記憶體相關的資訊了別。

2樓:白潔

多方面的因素(也許包括歷史因素),不存在對錯。c++的allocator就是user在free的時候傳入size,而c++ allocator的使用者主要是container類的author。std::

allocator::deallocate - cppreference.com

malloc/free, new delete,new/delete直接面向終端使用者,使用者素質良莠不齊,由使用者提供free size的話使用者還需要花心思取存這個size,出bug的概率更大

一些實現中小size allocation的allocation size和實際size不同,比如33byte、35byte的usersize都對應48byte大小的實際可用size, 這種情況下根本不需要使用者給size,給的size也不是實際分配的size

小size allocation用pool的情況下系統自己明確知道size大小,使用者的size給了也不用

3樓:Cooder

OS有成熟的記憶體管理, 如果free 要使用者自己指定申請的大小, 就會帶來幾個問題

效率、體驗會很差勁

可信嗎?記憶體管理會信使用者傳入的值嗎

4樓:

考慮到記憶體對齊,節約系統呼叫等因素,malloc實際分配的記憶體並不總是等於你申請的記憶體,因此在呼叫free()函式中無法準確的給出你具體需要歸還多少記憶體。

當然你也可以不這麼實現,乙個符合直覺的思路是在malloc內部放乙個hash_table ,記錄每個分配出去指標的大小,雖然這種思路在處理記憶體碎片合併的時候可能相對更困難一點。

5樓:

看了所有回答,有乙個關鍵點似乎沒有被答到:malloc的返回值(在釋放之前)是唯一的。

申請記憶體的返回值是乙個指標,指向乙個記憶體位址,多次呼叫malloc不會得到相同的返回值(free前),是唯一的。因此就只需要傳入申請到的記憶體位址即可正確free。

至於api將該記憶體區域的長度存放在什麼地方,就各有各的實現了,有就近放在前面的,也有統一放在某個全域性陣列裡。

6樓:康殼

這個問題我也問過自己,然後我研究了一下發現。malloc之後得到的指標它的前面有一段固定大小的資料,其中包含了這個指標管理的空間大小。因此你free的時候它只需要檢視你提供的指標前面的資訊,就知道釋放多少記憶體了。

7樓:麻瓜

因為申請的記憶體塊也是有元資訊的,比如在某個offset留乙個位元組記錄大小。如果大量申請小塊記憶體,這些元資訊暫用了大部分空間,利用率低,這就有了很多在malloc之上的allocator管理物件分配,提高記憶體利用率。

8樓:李大師

打個比方,你用紙做乙個箱子,剛好裝下四個籃球,你需要計算容積,長寬高,當你扔箱子,你拎著箱子就扔了,箱子本身已經有ID了,記憶體分塊,所以就不用高速它大小了。

9樓:氯乙烯

這個想法很好。因為長度你分配時候就已經被系統儲存起來了。你傳入時候根據指標就可以取到長度,最簡單辦法,做乙個hash表。儲存起來。釋放取出來釋放就好了。

10樓:望山

分配出去的記憶體塊大小是執行庫已知的,為了管理heap,執行庫需要儲存這個大小。為啥要程式設計師再提供一次呢?那才是奇怪的設計吧?

換個類似的問題,為什麼fopen需要傳入檔名而fclose不需要呢?如果題主這麼問,大家會不會覺得有點不對勁?

11樓:窗戶

從介面上思考這個問題,malloc你當然應該請求你希望向「系統」申請的長度,說白了就是在乙個管理大堆資源的銀行裡借一些資源,當然是需要資源的大小的,只是這個銀行比較慷慨,但再慷慨資源也有限,你得告訴銀行資源大小。銀行借了之後,只需要記錄你借錢的賬號即可。你去還資源的時候,銀行理論上是知道你當初申請了多少資源,於是你只要帶著賬號去就ok了。

12樓:

malloc是乙個標準,對應還有不同的實現,問題的核心在於為什麼標準可以這麼定,是否給不同的實現留有足夠的空間。

這裡可以舉乙個反例,在很多庫和框架中經常會出現名Context的引數,把所有可能需要的引數都塞在裡面。

而為什麼分配器不需要大小引數?

對於變長空間分配,常見的結構叫空閒列表,而空閒列表和使用列表(沒有這個詞,我生造的)是一體兩面的。分配器需要維護乙個鍊錶,每乙個節點包括起始位址和長度,這樣我們就知道哪些內存在使用,避免分配重疊的記憶體。

對於定長空間分配,每一塊記憶體是固定的大小,分配的時候只需要把分配的記憶體放進乙個合適的塊裡面。我們只需要根據位址定位到對應的塊就足夠(可以用位圖,鍊錶或者樹),而釋放是整塊釋放的,自然不需要長度。

13樓:啊哈

C語言標準就是這麼規定的:free無需手動指示大小。不是怕你不小心填錯,而是事實上你很難填對。

這是因為,雖然你告訴了malloc你要多少空間,但malloc真正分配了多少只有它自己知道。例如,你向malloc要了節,但某人寫的malloc分配的最小粒度是節,那麼你會得到乙個節的空間(雖然你一直以為它是節而不敢越雷池一步,這倒也沒什麼)。

所以,要是你填乙個錯誤值,還得讓它費心修正,還不如就讓它自己管理。

最常見的解決方案是,在malloc時,所分配的不僅是你請求的那點空間,還加了乙個資訊塊來記錄額外資訊,這個資訊塊位於你請求的空間前面。而malloc返回指標的指向的是你請求的空間,如果你想看看那個資訊塊的話,把malloc返回的指標往前走幾步就能看到了。

free所需的資訊可以直接在資訊塊中取。資訊塊和空間都會被釋放。

具體資訊塊有多大?它記錄的是位元組的多少?還是塊的數量?還記錄了啥?這都是依具體實現而定,並不統一。

顯然,以C語言的特點,這樣位置的資訊塊並不保險。如果你的指標越界寫入,破壞了其中的資訊,這樣錯誤會在free時候爆發。

還有,上面「在空間之前加資訊塊」的解決方案雖然是最常見的方案,但並不是所有C標準庫都會採用這個方案。只要能實現「free無需手動指示大小」這個要求,所有其他方案都可以。比如把資訊塊放在空間後面,或者遠離空間另乙個位置。

14樓:CagedBird

《c程式語言》(The C Programming Language)在8.7給出了乙個malloc與free的簡單實現,你可以看下大致思路。

15樓:printf鴻澤

至於為什麼要malloc要指定大小,乙個很簡單的原因,因為分配的時候需要在堆空間裡搜尋合適大小的空閒的塊,如果不指定空間的話可能不一定夠用,但每個塊不管是使用了的還是空閒的都會有乙個首部,記錄了塊使用的狀況和塊的大小,所以釋放的時候只要讀取塊的首部就知道大小了,再執行記憶體釋放演算法就可以了

16樓:IZAYOI

你使用 malloc 申請到的記憶體,得到的並不是你純粹想要的大小的記憶體空間,而是堆管理器幫你打包好的乙個 chunk。這個 chunk 就像乙個包裹,外面寫著包裹內容的相關資訊,其中就包含著包裹的大小資訊,而裡面的包裹內容就是你想要的記憶體。當你使用 free 想歸還這個包裹的時候,堆管理器看看包裹包裝上記錄的相關資訊,就知道包裹有多大了。

17樓:陸海綿

簡單來說,就是你申請記憶體的時候,作業系統把你申請的記憶體大小記下來了,等你釋放的時候,一查就知道當時給了你多少。

還有乙個問題,就是作業系統給你的記憶體大小跟你申請的可能不一樣,往往比你申請的要大一點,所以即使free的時候傳進引數,也是個沒用的數值,真實值還得查記錄。

至於作業系統怎麼記錄這塊記憶體的資訊,一般就是在你申請到的記憶體塊前面加個頭部資訊塊,free的時候直接就查你傳進去的位址的前面那塊,簡單高效,也埋下隱患,因為free不檢驗你傳進去位址是否是動態申請的。

18樓:Mathm

假如 free需要傳入大小,如果傳入的大小和malloc時的大小不一樣,小了會記憶體洩露,大了會破壞記憶體空間,既然free必須和malloc大小一樣,為啥還要把這個大小傳給free呢,free自己去取不好嗎!

C語言 和 的區別是啥

疑問三不知 乙個 是關係運算子,乙個 是賦值運算子,是用來比較變數之間的關係,變數與值之間的關係,是將等號右邊的值服給左邊的變數。 一劍封喉 c語言中乙個 是賦值的意思,而兩個等號 才是平時我們使用的等於號 如int a 12 就是把12賦值給a這個變數。15 3 18 中的等號在c中就用 表示 小...

有一定c語言和c 基礎,是看c primer plus 好還是看c primer好?

日月 如果基礎不是特別好,判斷標準先看primer,如果不懵逼,就一直看下去就行了,plus就不用看了。如果看了一部分就看不懂了,可以先看一下plus,plus的問題是很多寫法不是c 特別推薦的寫法,都是c風格!當然這兩本哪一本,都不太夠,因為作為新手,標準庫和boost還有很多值得學習的地方,不論...

用 Unity 3D 開發遊戲,熟悉 C 語言和 C 是否重要?

某個前同事老是分不清結構體和類型別的區別,被質問的時候解釋說 我已經修改它了,為什麼沒有生效 好想在這個問題下發個招聘廣告,不曉得會不會被封。還可以吧,如果C和C 了解的話,當使用unity3D引擎時,不會那麼吃力,C 比較容易入門,學起來的也比較輕鬆 c 在Unity開發遊戲中還是有用武之地,如果...