2016-01-13 182 views
-1

我最近研究關於的malloc()在下用聲明如下:兼容性()

void *malloc(size_t size) 

其中size_t是無符號的int和size定義沒有。的字節被保留。 問題是在我的系統上 float值佔用4字節的內存。所以,如果我使用2bytes的malloc的內存指針(浮點型),

float *p; 
p = (float *)malloc(2); 

那麼它怎麼沒有給出任何錯誤?因爲我認爲浮點數據需要4個字節,所以如果我只發出2個字節,那麼它可能會導致一些數據丟失。

還是我理解malloc()不正確?

+1

'size_t'不一定是'unsigned int'。不要依賴它。例如。在具有16位'int'但32個指針的系統上,它可能是'unsigned long'。在x64上它可能是'unsigned long long'(Windows,LLP64)或'unsigned long'(POSIX64,LP64)。 – Olaf

+0

您確實已經回答了您的問題。再讀一遍,看看你認爲錯的地方。記住C不會妨礙你(很多)射擊你的腳。 – Olaf

+0

我更關心問題的後半部分 – Lincoln

回答

2

在您給出的示例中,如果您只爲float *分配2個字節,然後嘗試通過取消引用指針來寫入該位置,則會寫入尚未分配的內存。這導致undefined behavior。這意味着它可能工作,它可能會轉儲核心,或者它可能以不可預知的方式運行。

如果你想爲一個或多個浮標分配內存時,你會做這樣的:

// allocates space for an array of 5 floats 
// don't cast the result of malloc 
int arrayLen = 5; 
float *f = malloc(sizeof(float) * arrayLen); 
1

如果您嘗試使用該指針 - 實際上指針正常,它指向的分配內存太小 - 編譯器無法將其識別爲錯誤的原因是這樣的一個事實,指針並不「知道」它指向的內容,實際上指針是包含內存地址的變量,所以基本上它們只是一個數字,並且在大多數情況下(如user694733指出的),指針的大小是相同的無論是指向一個空頭還是一個浮動。 編譯器看到的是從(void *)到(float *)的轉換以及編譯器,這是一個完全有效的轉換。

+0

*「指針的大小是相同的,無論它指向一個短的還是浮動的」*不一定。他們被允許有不同的內部表示。這裏'void *'被*轉換爲'float *'。 – user694733

+0

@ user694733指針本身是內存地址,所以它們在同一臺機器上具有相同的大小,而不管它們指向什麼。明確的演員陣容可以 - 在我看來應該放棄。 –

+0

應該刪除顯式轉換,因爲當'void *'被分配給其他指針類型時,C會執行*隱式轉換*。許多現代系統對所有指針類型使用相同的提示,但它不是C標準所要求的:可能仍然存在隱式轉換。 – user694733

0

你的問題實際上已經無關malloc的,而是在數據廣播。在這種情況下,您已將從malloc返回的地址開始的字節轉換爲float。因此,如果您稍後說*p = 0.0f;,您實際上會向所提及的內存區域寫入4個字節,但由於您只分配了2個字節,所以只需要2個字節就可以使用。因此,您的代碼將編譯和內存損壞運行(這要麼會導致死機,或更高版本的系統異常行爲)

1

您遇到的C Standard的要求執行特定的結果:

7.22.3存儲器管理功能

的順序和由連續調用分配給 的aligned_alloccallocmalloc,和realloc福存儲的鄰接沒有指定 。 如果分配成功返回的指針是 適當對齊,以便它可以被分配到指向任何類型的指針 對象具有基本對齊要求然後用於訪問這樣的對象或這樣的對象數組分配空間 (直到空間明確釋放)。

爲了提供存儲「適當地對準,使得它可以被分配給一個指針到任何類型的對象與基本對齊要求」,一個實施方案具有從malloc()在特定偏移返回存儲器這是系統最嚴格的對齊要求的倍數。這通常是8或16個字節。

鑑於返回每一個塊具有被對準這樣,大多數實現在內部的對齊要求倍數創建的存儲器塊。

所以如果你的系統有8字節對齊要求,你的malloc()實現可能實際上給你一個8字節的內存塊,即使你請求了兩個字節。同樣,要求19個字節,實際上你可能會得到24個字節。

它仍然不確定的行爲超越你問什麼,但。不幸的是,未定義的行爲包括「工作得很好」。