![](/img/trans.png)
[英]Why does this code emit buffer overrun warnings(C6385/C6386) in code analysis on Visual Studio 2012?
[英]Visual Studio 2015 Code Analysis C6386 warns of buffer overrun
我已經閱讀了很多關於 Visual Studio 代碼分析警告 C8386 的內容,但無法找出我的代碼的這個特定問題。 我將其簡化為以下小程序:
unsigned int nNumItems = 0;
int main()
{
int *nWords=nullptr;
unsigned int nTotal;
nTotal = 3 + 2 * nNumItems;
nWords = new int[nTotal];
nWords[0] = 1;
nWords[1] = 2; // this is line 18, warning C6386
delete[] nWords;
return 0;
}
分析->運行代碼分析->解決方案會給出以下警告:
file.cpp(18):警告 C6386:寫入“nWords”時緩沖區溢出:可寫大小為“nTotal*4”字節,但可能寫入“8”字節。
這是合法的嗎? 現在,如果我移動全局變量並將其設為本地變量,警告就會消失!
int main()
{
unsigned int nNumItems = 0;
...
}
但是我不能像在完整代碼中那樣這樣做,這是一個成員變量。
同樣,如果我將nTotal的定義移到“ new int ”中,我也可以刪除警告:
nWords = new int[3 + 2 * nNumItems];
但我不能這樣做,因為在完整代碼的其他地方提到了nWords 。
這只是 Visual Studio 靜態代碼分析器的問題,還是此代碼的合法問題?
靜態代碼分析很難,跟蹤像3 + 2 * nNumItems
這樣的表達式的可能值很難,而且跟蹤實際可能的值通常幾乎是不可能的。 這就是為什么它是警告而不是錯誤的原因。 到目前為止,顯而易見。
現在,看看你如何描述這個警告的行為,我會打賭一個“錯誤”,或者更確切地說,我應該在靜態分析器中用更少的壓力和缺陷來說它。
我可以在原始nWords[1] = 2
和全局nNumItems
上看到此警告背后的一些想象的可能原因。 它們真的很奇怪,我認為一個合理的分析師不會向分析器添加這樣的規則。 另外,我是對的,那么您也應該在nWords[0] = 1
上收到這些警告。
你沒有看到它們的事實證明我的想法是錯誤的,所以我到此為止。
相反,我想專注於靜態代碼分析很難。 分析器及其規則編寫得有多好並不重要。 在某些情況下,它會出錯,而在其他情況下,它只會失敗甚至無法猜測,而在其他情況下,它會超時並放手。 直到我們在 AI 方面取得突破或在解決 NP 難題方面取得突破,您可能不得不習慣這樣一個事實,即當您使用靜態代碼分析器時,您必須以他們可以理解的方式編寫代碼,不要指望他們能理解你能寫的一切。
最后想到,當我看到這個錯誤時:
file.cpp(18):警告 C6386:寫入“nWords”時緩沖區溢出:可寫大小為“nTotal*4”字節,但可能寫入“8”字節。
我注意到的第一件事是nTotal*4
和8
。 如果您使用的是硬編碼值,您可能會收到類似的錯誤
file.cpp(18):警告 C6386:寫入“nWords”時緩沖區溢出:可寫大小為“1024”字節,但可能會寫入“8192”字節。
您看到nTotal*4
的事實似乎暗示靜態代碼分析器實際上未能猜測nTotal
下的值, nTotal
其保留為符號名稱,從而形成了與8
無法比擬的表達式。 因此,分析儀做了它唯一能做的事情——它報告了一個問題,並盡可能地描述了它。 不過,這只是我的猜測。
// 編輯 - Dan 關於猜測的回答的注釋:nNumItems <- SIZE_MAX
我實際上認為他的 SIZE_MAX 可能相當。 我玩了一些微軟的 SAT 求解器,他們做得很好的一件事是解決整數域中的一組約束。 實際上unsigned int x = SIZE_MAX; std::cout << ( (3+2*x)*sizeof(int) );
unsigned int x = SIZE_MAX; std::cout << ( (3+2*x)*sizeof(int) );
打印 4(當然),這是表達式小於 8 的唯一x
值。
我很確定我玩過的微軟約束求解器在檢查整數環域中((3+2*x)*4) < 8
可滿足性時可以檢測到這種情況 - 因此可能會發出警告。 但是,我希望警告包含結果並打印如下內容:
nTotal*4 < 8 當 {nTotal=1,nNumItems=4294967295}`
因為分析器已經有了這些信息。 但是,那是......可能對它期望過高。 它背后的開發人員可能不會想到格式化如此詳細的警告消息,或者認為消息的當前格式對用戶更友好。
由於nNumItems
是全局的,代碼分析器似乎認為nNumItems
可能在您的代碼執行之前在其他地方設置為 SIZE_MAX。 您可以通過以下示例看到這一點:
size_t nNumItems = 0;
void foo()
{
nNumItems = SIZE_MAX;
}
void bar()
{
const size_t nTotal = 3 + 2 * nNumItems;
auto nWords = new int[nTotal];
nWords[0] = 1;
nWords[1] = 2;
}
int main()
{
foo();
bar();
return 0;
}
也許最好的解決方法是使用std::vector<int>
整個問題。
使 Global 成為常量:
const unsigned int nNumItems = 0;
這可能不是一個常見的解決方案,但就我而言,VS 產生了我認為是誤報的警告。 重新啟動 VS 后,警告消失了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.