[英]Allocating less memory than the specified size of a pointer-to-array
在 C 中,如果我們只訪問屬於已分配內存的元素,那么將內存分配不足給數組指針是否“合法”? 或者這是否會調用未定義的行為?
int (*foo)[ 10 ]; //Pointer to array of 10 ints
foo = malloc( sizeof( int ) * 5 ); //Under-allocation! Only enough memory for 5 ints
//Now we only ever access (*foo)[ 0 - 4 ]
如果這本身不是未定義的行為,那么訪問另一個不相關的對象,其內存地址恰好落在數組未分配部分的地址空間內會導致嚴格別名違規嗎?
這是未定義的行為。
foo
應該指向int[10]
類型的對象(或對象數組中的第一個)。 您沒有分配那么多空間,因此類型為int[10]
的表達式*foo
訪問該類型的對象,但這樣做會讀取已分配內存段的末尾。
正如@dbush 在他的回答中所描述的,一個數組被定義為元素類型(C17 6.2.5/20)的一組連續分配的非空對象。 顯然, malloc( sizeof( int ) * 5 )
沒有為int[10]
分配足夠的空間。
但是我發現很難正式支持該答案的最后一部分,聲稱大小差異使(例如) (*foo)[4]
具有未定義的行為。 這個結論似乎是有道理的,但標准實際上在哪里這么說的?
這里的主要問題之一是(動態)分配的對象沒有聲明類型,只有在某些情況下,有效類型取決於它們的訪問方式和訪問方式。 (C17 6.5/6 和腳注 88)。 我們確實知道,如果成功, malloc(n)
返回一個指向大小為n
的對象的指針(C17 7.22.3.4/2),但是我們如何將未定義的行為具體歸因於與描述對象的有效類型的對象的關聯?尺寸大於n
?
我最終決定連接點的最佳方法如下。 假設o
是大小為n
已分配對象, T
是sizeof(T) > n
的完整類型,並且o
是通過T
類型的左值讀取或寫入的。 然后第 6.5/6 段將有效類型T
歸因於對象o
,但由於o
的大小不足,我們必須得出結論,它的表示構成了類型T
(C17 3.19.4) 的陷阱表示。 然后第 6.2.6.1/5 段重申了“陷阱表示”的定義,並讓我們到達了我們想要去的地方:
某些對象表示不需要表示對象類型的值。 如果對象的存儲值具有這樣的表示形式並且被沒有字符類型的左值表達式讀取,則行為未定義。 如果這種表示是由沒有字符類型的左值表達式修改對象的全部或任何部分的副作用產生的,則行為是未定義的。 這種表示稱為陷阱表示。
(加了重點。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.