2012-07-31 119 views
3

在閱讀this SO question的答案時,我瞭解到超出邊界的指針算術是未定義的。實際上,根據C99 6.5.6段落8釋放指針算術

如果 指針操作數兩者,並將結果指向相同 陣列對象的元素,或一個過去的陣列 對象的最後一個元素時,評估應不產生溢出; 否則,行爲是不確定的。

釋放該對象是否使該保證無效? 7.20.3.2「自由功能」似乎沒有提到它,只是提到「空間被釋放」。由於6.5.6特別提到了溢出問題,它看起來像是一個整數溢出問題,免費不會影響。算術是指向一個對象的指針是「引用它」的行爲?

換句話說,就是:

char *foo = malloc(10); 
free(foo); 
foo++; 

不定?或者是「溢出」使用另一個?

+1

釋放指針後,它不再指向數組。這就排除了「指向相同數組對象的元素」,當它沒有指向任何東西時。 – 2012-07-31 22:41:08

回答

5

C99第6.2.4節說:當對象指向 至到達其壽命的終點

一個指針的值變爲不確定的。

§7.20.3描述分配對象的生存期,如通過malloc()創建:

一個已分配對象的生存期從分配延伸直到 的解除分配。

所以,正式地說,指針foo的值free()後變得不確定,並且因此可以不再被說成指向任何對象。因此增量的行爲是不確定的。

+1

那麼,即使打印指針也是不確定的?一個有效的C運行時可以遍歷所有內存,將所有用於指向釋放對象的指針置空? – Dave 2012-07-31 06:05:14

+1

@Dave:*值*變得不確定,所以如果你使用指針值(使用'%p',或者將它轉換爲整數並打印出來),那麼它是未定義的。但我不相信底層表示會變得不確定 - 如果你以'unsigned char'數組的形式訪問它,那麼它應該保持不變。所以構成指針的字節保持不變,但是它們的*含義*作爲指針變得不確定。 – caf 2012-07-31 06:39:45

+2

你甚至不能依靠組成指針的字節保持不變。 C標準在這方面允許很大的自由度。考慮一個進程必須管理自己的內存的實現,因爲硬件不支持虛擬內存。在該實現中,指針可以被實現爲存儲器中具有附加信息的結構的地址,例如實際數據的磁盤位置。指針的「值」會包含這些附加信息。 (接下頁) – 2012-07-31 08:38:04

1

對無效指針執行算術調用未定義的行爲。

+1

根據C標準6.5.6的第8段,有限邊界外指針的算術運算會導致未定義的行爲。 – 2012-07-31 08:42:04

-1

這裏foo是一個指針變量,它將存儲地址爲char。實際上,該地址將是一個虛擬地址。

因此,如果我們對變量foo執行任何指針算術將導致根據指針變量的類型增加值。這不會被視爲未定義的行爲。

+2

根據C標準,這是未定義的行爲。正如caf的答案所指出的那樣,指針的值是不確定的。而且,按照C標準6.5.6的第8段,在這樣的指針上進行算術運算會導致未定義的行爲。 – 2012-07-31 08:41:30