2013-07-29 52 views
10

我讀理查德·里斯的新的(2013年5月)O'Reilly出版的「瞭解和使用C指針,指向」,我有一個關於一些代碼其中的問題,第85頁上realloc後使用原始指針?

if (++length > maximumLength) { 
    char *newBuffer = realloc (buffer, maximumLength += sizeIncrement); 

    if (newBuffer == NULL) { 
     free (buffer); 
     return NULL; 
    } 

    currentPosition = newBuffer + (currentPosition - buffer); 
    buffer = newBuffer; 
} 

我希望的名字變量是不言自明的;如果需要上下文,我將編輯以提供整個代碼塊,而不僅僅是這個摘錄。

我的問題是關於行currentPosition = newBuffer + (currentPosition - buffer);。我對realloc()的理解是,當新分配成功時,最初分配的內存被釋放。如果這是正確的,那麼有問題的線路正在使用懸掛指針,無辜?該表達式的RHS上的buffercurrentPosition都是指向已被釋放的內存的指針。

我的直覺是重寫這個,以避免使用懸掛指針通過使用length,畢竟它已經在附近。我想,以取代最後兩行:

buffer = newBuffer; 
currentPosition = buffer + length; 

然而,想必代碼寫的作品,因爲這兩個指針仍持有地址(儘管垃圾),以及這兩個地址之間的偏移仍然可以被計算爲一種重新分配的方式currentPosition。那麼,我是否只是在對此感到不安呢?

爲了概括這個問題:一旦指針懸空,是否可以安全地使用包含在指針中的地址用於任何目的,比如計算偏移量?謝謝。

+0

在重新分配時,「length」大於緩衝區的大小(調整前的maximumLength)。如果我正確解釋意義,你應該使用'currentPosition = buffer + length - 1'。 – Casey

+0

實際上,我在發佈問題之前檢查過。該書的代碼將「length」和「currentPosition」初始化爲零。 'length'在第一個條件中增加,所以它總是超過最後一個添加的元素的索引。 'currentPosition'是新元素被添加的地方,並且在添加之後得到遞增。這不是我如何編寫代碼開始的,但是按照給定的代碼,'buffer + length'是正確的。 – verbose

+0

所以'currentPosition'是一個預先組成的'buffer + length'?我立場糾正(並且被冗餘略微困惑)。 – Casey

回答

9

一旦指針懸空,是否可以安全使用包含在指針中的地址用於任何目的,例如計算偏移量?

不,這是不安全的。在free之後,指針值是無效地址,無效地址不能用於指針算術而不調用未定義的行爲。

+0

來源?我沒有預料到這一點。 –

+2

@CoryNelson C11,6.5.6p8指針算術。如果結果不在數組對象中或者超過最後一個元素=>未定義的行爲。 – ouah

+1

@Ouah,我認爲這是指您嘗試解除結果的引用。 – ROTOGG

0

只要您不嘗試解除引用指針(即應用操作符*),則使用懸掛指針(例如「指針算術」)是安全的。

+3

這是錯誤的,因爲C標準不能保證以前指針對不再存在的對象的算術有效。你可能會認爲指針是作爲內存地址來實現的,算術地址顯然起作用,但指針不一定以這種方式實現。此外,允許優化器根據C的規則進行扣減,這可能導致令人驚訝的行爲。 –