通过VS地址擦除系统定位缓冲区溢出问题

发布时间 2023-12-10 17:38:11作者: 西兰花战士

VS2019增加了一个名为“地址擦除系统”的功能,默认是关闭的,可以在项目“属性”-“c/c++”-"常规"中开启。在开启地址擦除系统”功能时,将调试信息格式设置为“程序数据库”。如下图:

如果没有该项,检查VS2019的版本是否低于16.9,并且在安装项中是否安装“C++ AddressSanitizer”。如下图:

下面用一些缓冲区溢出的例子,让编译器帮忙判断出错位置。

全局缓冲区溢出

 1 #define _CRT_SECURE_NO_WARNINGS
 2 #include <iostream>
 3 using namespace std;
 4 
 5 char sBuf[5];
 6 int main()
 7 {
 8     int nNum = 1;
 9     strcpy(sBuf, "Hello World!");
10 
11     for (int i = 1; i < 101; i++)
12         nNum += i;
13 
14     cout << "Num = " << nNum << endl;
15     getchar();
16 }

在上面代码中,定义了一个容量为5字符数组,将"Hello World!"字符串拷贝至该空间中,很明显这里发生了溢出。在不开启“地址擦除系统”功能下,能正常执行,不会有任何错误提示。如下图:

开启“地址擦除系统”功能,程序崩溃。

堆栈缓冲区溢出

 1 #define _CRT_SECURE_NO_WARNINGS
 2 #include <iostream>
 3 using namespace std;
 4 
 5 int main()
 6 {
 7     int nNum = 0;
 8     char sBuf[5];
 9     strcpy(sBuf, "Hello World!");
10 
11     for (int i = 1; i < 101; i++)
12         nNum += i;
13 
14     cout << "Num = " << nNum << endl;
15     getchar();
16 }

上面代码在不开启“地址擦除系统”功能下,数据计算异常,原因是在调用strcpy函数时,溢出部分的数据写入了nNum地址中,导致nNum计算的值出错:

观察内存分布情况:

 在实际工程中,如果遇到这种问题,定位是相当复杂的。开启后,调用strcpy函数直接崩溃:

堆缓冲区溢出

堆缓冲区和上面两种差不多,就不放代码了。