教訓:malloc之前確認malloc的長度是否爲0

教訓:malloc之前確認malloc的長度是否爲0

導致問題:segment fault段錯誤的問題,這種問題很難尋找,所以要避免malloc(0),如果出現類似問題可以二分法加打印定位問題點。

問題分析:

  初始化在堆上malloc了一塊區域,但是malloc()的size爲0,這塊地址被用來存了很多數據,數據依然可以使用,但是存的數據會將其他地址踩掉,就會在用其他地址的時候存在segment fault段錯誤問題

關於malloc(0)

  在標準的malloc實現中,並不檢查輸入值的大小,而是將輸入值做對齊操作後直接從堆上分配空間。
  不論輸入值的大小爲多少,在malloc的內部最小的內存分配大小是一個定值(一般是8B),因爲malloc需要用這部分空間來維護堆上的內存塊鏈表。所以當用戶申請一塊0B的空間時,malloc實際分配的空間是8B,如果用戶申請的空間是X,則malloc實際分配的空間是(對齊(X)+8)。這也是爲什麼malloc分配的空間千萬不能越界使用的原因:堆的內部鏈表結構將被破壞。
  
  對於new和delete malloc和free這樣的內存分配與釋放函數:到底delete和free是怎麼知道要釋放掉多少內存的呢?
  其實在new和malloc內存分配成功時,系統除了返回一個指向這塊內存的指針外,還會獲得一塊用於記錄此處分配的內存大小的內存塊
  
  在內存管理中,內存被分爲兩部分:棧和堆。
  棧有自己的機器指令,是一個先進後出的數據結構。
  malloc分配的內存是堆內存,由於堆沒有自己的機器指令,所以要有系統自己編寫算法來管理這片內存,通常的做法是用鏈表,在每片被分配的內存前加個表頭,裏面存儲了被分配內存的起始地址和大小,你的malloc返回的就是表頭裏的起始指針,這個地址是由一系列的算法得來了,通常不會爲0,一旦分配成功,就返回一個有效的指針,對於分配0空間來說,算法已經算出可用內存的起始地址,但是你佔用0空間,所以對那個指針操作就是錯誤的,操作系統一般不知道其終止地址,因爲有佔用大小就可以推出終止地址,還有就是即使分配0空間也要釋放它,其實是釋放的鏈表結點。

sample

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char* temp = NULL;
    temp = malloc(0);
    printf("the address of temp = %p\n", temp);
}

輸出結果:

the address of temp = 0x685010

說明malloc(0)是會返回malloc的地址,只是malloc的地址長度爲0

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章