我在 C 中有一個簡單的練習(見下面的代碼)。該程式采用具有三個分量的向量并將每個分量加倍。該IDE給我這個警告(綠色波浪線):C6011 dereferencing null pointer v.在這一行:v[0] = 12;。我認為這是一個錯誤,因為在除錯器中我閱讀了the program exited with code 0. 你怎么看待這件事?
#include <stdlib.h>
#include <stdint.h>
void twice_three(uint32_t *x) {
for (size_t i = 0; i < 3; i) {
x[i] = 2 * *x;
}
}
int main(void) {
uint32_t *v = malloc(3 * sizeof(uint32_t));
v[0] = 12;
v[1] = 59;
v[2] = 83;
twice_three(v);
free(v);
return 0;
}
注意:我正在使用 Visual Studio。
uj5u.com熱心網友回復:
我相信您的 IDE 正在警告您,您沒有確保malloc回傳NULL. 當您用完要分配的記憶體時malloc可以回傳NULL。
是否需要這樣的檢查是有爭議的。萬一malloc回傳NULL,您的程式最終會被殺死(在具有虛擬記憶體的現代計算機上)。所以問題是在非常罕見的記憶體不足的情況下,您是否想要一個干凈的訊息。
uj5u.com熱心網友回復:
- 始終檢查 malloc 的結果。
- 使用未輸入的物件
sizeof
int main(void) {
uint32_t *v = malloc(3 * sizeof(*v));
if(v)
{
v[0] = 12;
v[1] = 59;
v[2] = 83;
twice_three(v);
}
free(v);
return 0;
}
uj5u.com熱心網友回復:
首先,請注意警告是由您的編譯器(或靜態分析器或 linter)生成的,而不是由您最初撰寫的除錯器生成的。
警告告訴您您的程式可能會取消參考空指標。出現此警告的原因是您執行 amalloc()然后使用結果(指標)而不檢查 NULL 值。在這個特定的代碼示例中,malloc()很可能只回傳請求的記憶體塊。在任何臺式計算機或筆記本電腦上,通常沒有理由無法分配 12 個位元組。這就是為什么您的應用程式運行良好并成功退出的原因。但是,如果這將是更大應用程式的一部分和/或在記憶體有限的系統(例如嵌入式系統)上運行,則malloc()可能會失敗并回傳NULL. 注意malloc() 如果沒有足夠的可用記憶體,它不僅會失敗,如果由于碎片而沒有足夠大的連續可用記憶體塊,它也會失敗。
根據 C 標準,取消參考 NULL 指標是未定義的行為,這意味著任何事情都可能發生。在現代計算機上,它可能會殺死您的應用程式(這可能導致資料丟失或損壞,具體取決于應用程式的功能)。在較舊的計算機或嵌入式系統上,該問題可能未被檢測到,您的應用程式將從地址 NULL 讀取或(更糟的是)寫入地址 NULL(這很可能是 0,但即使是 C 標準也不能保證)。這可能會在發生這種情況后的任意時間導致資料損壞、崩潰或其他意外行為。
請注意,編譯器/分析器/linter 對您的應用程式或將在其上運行的平臺一無所知,并且不會對此做出任何假設。它只是警告您這個可能的問題。您可以自行決定此特定警告是否與您的情況相關以及如何處理。
一般來說,你可以做三件事:
如果您確定這
malloc()永遠不會失敗(例如,在這樣一個玩具示例中,您只能在具有千兆位元組記憶體的現代計算機上運行)或者如果您不關心結果(因為應用程式將被殺死)您的作業系統,并且您不介意),則不需要此警告。只需在編譯器中禁用它,或忽略警告訊息。如果你不希望
malloc()失敗,但這樣做要當它發生時被告知,快速和骯臟的解決辦法是增加assert(v != NULL);malloc的后。請注意,這也將在發生時退出您的應用程式,但以稍微更可控的方式,您將收到一條錯誤訊息,說明問題發生的位置。我會推薦這個用于簡單的愛好專案,你不想在錯誤處理和極端情況上花費太多時間,而只想進行一些有趣的編程:-)當實際更改
malloc()會失敗并且您希望應用程式具有明確定義的行為時,您絕對應該添加代碼來處理這種情況(檢查 NULL 值)。如果是這種情況,您通常需要做的不僅僅是添加 -if陳述句。您必須考慮應用程式如何在不需要更多記憶體分配的情況下繼續作業或正常關閉。在嵌入式系統上,您還必須考慮諸如記憶體碎片之類的問題。
有問題的示例代碼最簡單的修復方法是添加 NULL 檢查。這將使警告消失,并且(假設malloc()不會失敗)您的程式將繼續運行。
int main(void) {
uint32_t *v = malloc(3 * sizeof(uint32_t));
if (v != NULL) {
v[0] = 12;
v[1] = 59;
v[2] = 83;
twice_three(v);
free(v);
}
return 0;
}
注意:我建議用if (v != NULL)代替if (!v),因為NULL不能保證是0(盡管它適用于超過 99% 的平臺)并且它更好地描述了代碼的意圖,恕我直言。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/361014.html
