簡體   English   中英

Visual Studio 2015 代碼分析 C6386 警告緩沖區溢出

[英]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*48 如果您使用的是硬編碼值,您可能會收到類似的錯誤

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM