簡體   English   中英

GCC `-fsanitize=bounds` 與 `std::array` 的奇怪行為

[英]GCC `-fsanitize=bounds` strange behaviour with `std::array`

我正在嘗試使用-fsanitize=bounds選項在我的代碼中找出越界問題,但我遇到了奇怪的行為:

例如在以下代碼中:

#include <cstdlib>
#include <array>

int main (int, char **)
{
    std::array <char, 1> a;
    const char b = a [X]; // X <--- put index here!

    return EXIT_SUCCESS;
}

編譯選項: $ g++ -std=c++11 -fsanitize=bounds -O0 main.cpp -o main

如果我嘗試訪問索引大於 1 的元素,則會報告錯誤: /usr/include/c++/5/array:53:36: runtime error: index 2 out of bounds for type 'char [1]'

但是,如果我嘗試訪問索引為 1 的元素 - 一切正常並且不會報告任何錯誤。

這是預期的行為,可能是我錯過了什么?

該示例在以下方面進行了測試:
- $ g++ --version g++ (Ubuntu 5.4.0-6ubuntu1~16.04.2) 5.4.0 20160609 ;
- $ g++ --version g++ (Ubuntu 6.2.0-5ubuntu12) 6.2.0 20161005

UPD
我在 GCC 6 中嘗試過-fsanitize=bounds-stric並且結果相同。

我無法立即找到這方面的文檔(或者,實際上,任何類型的強大文檔),但它很可能是這個功能的實現細節。 獲得一個過去的指針是合法的,因此實現無法捕獲這一點。 似乎實現通過查看指針來工作,而不是等待這樣的指針被解除引用(如果你考慮如何創建-fsanitize=bounds ,這是有道理的)。

簡而言之,這可能僅僅是對工具的限制。

在GCC 6中,您可以嘗試-fsanitize=bounds-strict ,這會增加工具的強度(包括添加對檢測對類似靈活成員的數組的OOB訪問的支持)。

我無法分辨這是一個庫還是編譯器問題,但無論哪種方式,值得注意的是同一個問題目前是針對clang的開放式錯誤( #21485 ),並且評論中的假設與我上面的ramblings相匹配。

關於ubsan的第三方文章也暗示這最終是預期的行為。

來自https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html

-fsanitize = bounds此選項啟用數組邊界的檢測。 檢測到各種越界訪問。 靈活的數組成員,靈活的數組成員類數組和具有靜態存儲的變量的初始化器不會被檢測。

使用X> 1使得此檢查(數組越界)觸發,正如預期的那樣,因為'a'字符聲明,size = 1。

編輯

正如那樣說,正如Orbit的OrLights Races所說,這不是一個答案。 但是為讀者提供了一些信息。

情況X == 1是一個過去的事實使我想到迭代器,其中允許一個過去的結束。 IOW,GCC清理工具似乎得到了一個迭代器來測試,而不是參考a [X]。

@Gluttton確認使用類C數組而不是std :: array情況a [1]顯示為錯誤,如預期的那樣。

正如@Ripi2 提到的,數組末尾的第一個元素通常被視為結束迭代器。

在這種情況下, -fsanitize=address可以檢測越界錯誤,當您訪問數組的非法位置時,編譯器可以提供更多信息。

g++ -std=c++11 -fsanitize=address -O0 main.cpp -o main

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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