[英]Why does the C compiler not warn about malloc size errors?
我創建了一個成員結構,該結構是在我的 iOS 應用程序的 ViewDidLoad 中分配的。 我使用 malloc 為這個結構分配空間,然后在我的課堂上使用。 像這樣:
self.myData = malloc(sizeof(MyData));
除了我真正做的是:
self.myData = malloc(sizeof(MyOtherStruct));
我不小心在 malloc 調用中將 sizeof() 設置為不同的結構(大小不同)。 我很長一段時間沒有注意到這個錯誤,因為該應用程序很少崩潰。 操作系統更新導致崩潰更頻繁地發生。
我的問題是,為什么編譯器不能對這種事情發出警告? 這是編譯器不知道的東西,還是允許用戶隨意分配任何大小的設計選擇?
“我怎樣才能更快地找到這個錯誤?”
有很多方法可以更快地找到錯誤。
靜態分析器會捕獲此錯誤。 在 Xcode 中按 command-shift-B。 例如,采用以下代碼:
#include <stdlib.h>
struct x { double x; };
struct y { char y; };
int main(int argc, char **argv) {
struct x *p = malloc(sizeof(struct y));
p->x = 1.0;
return 0;
}
運行分析器對我產生了這個錯誤:
'malloc' 的結果被轉換為類型為 'struct x' 的指針,該指針與 sizeof 操作數類型 'struct y' 不兼容
建議以這種方式編寫代碼:
self.myData = malloc(sizeof(*self.myData));
以后就這樣做吧。 這不僅不容易出錯,而且更容易記住。
使用 Swift 或 C++ 之類的語言,其中語言的類型系統可以幫助您避免此類錯誤。 C 在很多方面都不太寬容。 它是在70年代初發明的,你只是一種必須接受,如果你想使用它,而這些類型的錯誤是為什么C ++和斯威夫特在首位,甚至存在的理由的重要組成部分。
使用運行時內存邊界檢查器,如地址清理器。 這將在訪問內存時檢測錯誤,而不是在分配內存時檢測錯誤,但它仍會為您提供訪問和分配(如果內存已釋放,則為空閑)的堆棧跟蹤。 現在任何寫 C 的人都應該熟悉 address sanitizer 及其朋友,tsan,ubsan 等。
Valgrind 也實現了相同的效果,但地址清理器對於常見用例具有更好的用戶體驗。
編譯器只真正為您提供類型錯誤的錯誤和警告。 這不是類型錯誤,而是運行時錯誤。 編譯器可以檢測到一些“可能”的運行時錯誤,但數量很少。 諸如忘記使用malloc()
的返回值之類的事情……例如,
void f(void) {
malloc(1); // warning
}
編譯器也好不到哪里去。
同樣,這是 C++ 和 Swift 等新語言的推動力,它們的類型系統允許您在分配錯誤時產生錯誤,這也是靜態分析(這是一個棘手的問題)的推動力。
發生這種情況是因為 ARC 沒有責任處理malloc()
甚至free()
ARC 只處理分配的對象,如[Object alloc]
在你的情況下,當你做self.myData = malloc(sizeof(MyOtherStruct));
,例如可以解釋為:
self.myData = malloc(N*sizeof(MyData));
//what can represents self.myData[0]..self.myData[N-1]
最后,記住當你使用sizeof()
,它會告訴你類型的大小,你作為參數傳遞,在編譯時計算。
您可以查看此鏈接以獲取有關對象分配的更多信息
並查看有關內存分配的Apple 文檔
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.