錯誤: global-buffer-overflow
位址清理程式錯誤:全域緩衝區溢位
編譯器會針對 或 .bss
區段中的任何變數 .data
產生中繼資料。 這些變數具有全域或檔案靜態的語言範圍。 在開始之前 main()
,它們會配置在記憶體中。 C 中的全域變數處理方式與 C++ 大不相同。 此差異是因為連結 C 的複雜規則。
在 C 中,全域變數可以在數個原始程式檔中宣告,而且每個定義都可以有不同的類型。 編譯器一次看不到所有可能的定義,但連結器可以。 針對 C,連結器預設會從所有不同的宣告中選取大小最大的變數。
在 C++ 中,編譯器會配置全域。 只能有一個定義,因此每個定義的大小在編譯時期都是已知的。
範例 - 具有多個類型定義的 'C' 全域
// file: a.c
int x;
// file: b.c
char* x;
// file: c.c
float* x[3];
// file: example1-main.c
// global-buffer-overflow error
// AddressSanitizer reports a buffer overflow at the first line
// in function main() in all cases, REGARDLESS of the order in
// which the object files: a.obj, b.obj, and c.obj are linked.
double x[5];
int main() {
int rc = (int) x[5]; // Boom!
return rc;
}
若要建置及測試此範例,請在 Visual Studio 2019 16.9 版或更新版本的 開發人員命令提示字元 中執行下列命令:
cl a.c b.c c.c example1-main.c /fsanitize=address /Zi
devenv /debugexe example1-main.exe
產生的錯誤
範例 - 簡單函式層級靜態
// example2.cpp
// global-buffer-overflow error
#include <string.h>
int
main(int argc, char **argv) {
static char XXX[10];
static char YYY[10];
static char ZZZ[10];
memset(XXX, 0, 10); memset(YYY, 0, 10); memset(ZZZ, 0, 10);
int res = YYY[argc * 10]; // Boom!
res += XXX[argc] + ZZZ[argc];
return res;
}
若要建置及測試此範例,請在 Visual Studio 2019 16.9 版或更新版本的 開發人員命令提示字元 中執行下列命令:
cl example2.cpp /fsanitize=address /Zi
devenv /debugexe example2.exe
產生的錯誤 - 簡單函式層級靜態
範例 - C++ 中的所有全域範圍
// example3.cpp
// global-buffer-overflow error
// Run 4 different ways with the choice of one of these options:
//
// -g : Global
// -c : File static
// -f : Function static
// -l : String literal
#include <string.h>
struct C {
static int array[10];
};
// normal global
int global[10];
// class static
int C::array[10];
int main(int argc, char **argv) {
int one = argc - 1;
switch (argv[1][1]) {
case 'g': return global[one * 11]; //Boom! simple global
case 'c': return C::array[one * 11]; //Boom! class static
case 'f':
{
static int array[10] = {};
return array[one * 11]; //Boom! function static
}
case 'l':
// literal global ptr created by compiler
const char *str = "0123456789";
return str[one * 11]; //Boom! .rdata string literal allocated by compiler
}
return 0;
}
若要建置及測試此範例,請在 Visual Studio 2019 16.9 版或更新版本的 開發人員命令提示字元 中執行下列命令:
cl example3.cpp /fsanitize=address /Zi
devenv /debugexe example3.exe -l
產生的錯誤 - C++ 中的所有全域範圍
另請參閱
AddressSanitizer 概觀
AddressSanitizer 已知問題
AddressSanitizer 組建和語言參考
AddressSanitizer 執行時間參考
AddressSanitizer 陰影位元組
AddressSanitizer 雲端或分散式測試
AddressSanitizer 偵錯工具整合
AddressSanitizer 錯誤範例
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應