2013-09-26 41 views
3

calloc(10,4)和calloc(1,40)之間的區別是什麼?calloc(10,4)和calloc(1,40)之間的區別是什麼?

我看到這種行爲:

Thing** things = (Thing**)calloc(1, 10 * sizeof(Thing*)); 
// things[0] != 0 

Thing** things = (Thing**)calloc(10, sizeof(Thing*)); 
// things[0] == 0 

我想知道爲什麼。編輯:失去我的想法是爲什麼,現在都似乎導致零...至少使問題有趣,爲什麼calloc不只是採取一個單一的參數,如malloc?

+0

+1;我自己想過這個。我想知道在所有情況下它是否完全一樣;即標準的任務是這樣嗎? – Bathsheba

回答

3

在實踐中它是相同的。但是這有一個重要的特點給你。

假設您從網絡接收到一些數據,並且該協議有一個字段,指定一個數組將包含多少個要發送給您的元素。你這樣做:

uint32_t n = read_number_of_array_elements_from_network(conn); 
struct element *el = calloc(1, n * sizeof(*el)); 
if (el == NULL) 
    return -1; 
read_array_elements_from_network(conn, el, n); 

這看起來無害,不是嗎?好吧,不是那麼快。連接的另一端是邪惡的,並且實際上向您發送了一個非常大的數字作爲元素的數量,以便乘法包裝。假設sizeof(*el)爲4,並且n被讀爲2^30+1。乘法2^30+1 * 4換行並且結果變爲4,這就是您在告訴函數讀取2^30 + 1元素時分配的內容。 read_array_elements_from_network函數將很快溢出您分配的數組。

calloc的任何體面的實施都將檢查該乘法中的溢出並且將防止這種類型的攻擊(這種錯誤非常普遍)。

+0

+1溢出在DOS 16位日更爲明顯。 – chux

1

這是一樣的。該分配確實將元素的數量乘以一個元素的大小來分配大小。

沒關係,因爲它將是一個街區。

0

它實際上是相同的,因爲分配塊是連續的。它分配number_of_elements * size_of_element,所以10個大小爲4的元素或1個大小爲40的元素最終分配40個字節。

0

我想答案爲什麼calloc有兩個參數是我們程序員可以活得更長,用於輕鬆地編寫代碼,或讀code.Many事情有這樣的解釋:)

相關問題