黔西南州信息港

当前位置:

运行时和编译时的安全性检查RTC

2019/06/19 来源:黔西南州信息港

导读

RTC 表示运行时检查。RTC 有若干子选项。与 /GS 不同,/RTC 设计用于调试版本,而不用于优化代码。与 /GS 相同的是,如果您不

  RTC 表示运行时检查。RTC 有若干子选项。与 /GS 不同,/RTC 设计用于调试版本,而不用于优化代码。与 /GS 相同的是,如果您不喜欢默认对话框,可以编写自己的处理程序。

  使用 Microsoft Visual Studio 调试应用程序时,RTC 对话框可以为您提供在错误发生之处调试应用程序的选项。此外,还可以在 Visual Studio 中创建若干个配置,每个配置都包含各种选项的不同组合,例如,对发布版本使用 /GS 选项,而对调试版本使用一个或多个 /RTC 选项。

  /RTCs - 堆栈帧运行时错误检查此选项在保护堆栈不被破坏方面采取了若干措施。

  在每次调用函数时,将所有局部变量初始化为非零值。这样可以防止以前的调用对堆栈中的值的无意使用。

  验证堆栈指针能够检查到堆栈破坏,例如,在一个位置将函数定义为 __stdcall,而在另一个位置将函数定义为 __cdecl 可导致堆栈破坏。

  检测局部变量的溢出和不足。这与 /GS 不同,因为它仅适用于调试版本,并且检测缓冲区的两端以及所有缓冲区是否遭到破坏。

  cl /Od /MLd /ZI /EHsc /RTCs p

  此命令将关闭优化 (/Od),并设置 _DEBUG 预处理器定义。

  使用此命令编译样例后,请再次尝试运行 测试 1。此时它将会捕捉到覆盖操作。

  测试 2 说明了不包括返回地址的堆栈溢出:

  void Test2(){ char buffer1[100]; char buffer2[100]; buffer1[0] = 0; for (int i=0 ; i = sizeof(buffer2); i++) { buffer2[i] = 'a'; } buffer2[sizeof(buffer2)-1] = 0; cout buffer2 '-' buffer1 endl;}

  此循环使 buffer2 溢出一个字符,因为它使用 = 代替了 。它将覆盖 buffer1 的个字符。使用 /RTCs 编译器开关进行编译并使用 gs-rtc 2 运行时,系统将显示下面的对话框:

  图 3. 使用 gs-rtc 2 选项时生成的错误。

  测试 3 对缓冲区不足进行了说明:

  void Test3(){ char buffer1[100]; char buffer2[100]; memset(buffer1,'a',sizeof(buffer1)-1); buffer1[sizeof(buffer1)-1]=0; memset(buffer2,'b',sizeof(buffer2)-1); buffer2[sizeof(buffer2)-1]=0; *(buffer) = 'c'; cout buffer1 endl; cout buffer2 endl; }

  (要运行测试 3,请使用命令“gs-rtc 3”。)在本例中,buffer2 的一个字节被覆盖,并且对话框将显示 buffer1 出现的问题。如果不进行运行时检查,此测试的输出结果为:

  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

  由于这一写入操作破坏了 buffer2 的终止符,因此,所有将 buffer2 用作空结束字符串的操作都将获得一个长度为期望值两倍的字符串。

  测试 4 显示了 /RTCs 选项如何将未初始化变量设置为“标志”值:

  void Test4(){ unsigned int var; cout hex var;}

  在使用 /RTCs 编译之后运行 测试 4时,将得到十六进制值 cccccccc。如果不使用 /RTCs 进行编译,将得到堆栈中剩余的随机值。

  /RTCc - 检测导致数据丢失的分配此选项将插入代码,以便在分配导致数据丢失时向您发出警报,这样可以确保在转换为较小类型时从不丢失数据。测试 5 说明以下内容。

  void Test5(int value){ unsigned char ch; ch = (unsigned char)value;}

  请执行以下命令来编译此代码:

  cl /Od /MLd /ZI /EHsc /RTCc p

  请在命令提示符处使用其他数字来运行此命令。例如,此命令将触发错误:

  gs-rtc 5 300

  图 4. 在 /RTCc 开关中使用大于 255 的数值时所生成的错误。

  无符号字符多可容纳 255 个字符,因此向程序中输入 300 将导致数据丢失。使用 gs-rtc 5 200 再次运行命令,此时将不会出现错误。

  如果要转换为较小类型,并要故意丢失上面的数位,则可以使用如下所示的掩码:

  ch = (unsigned char)(value 0xFF);

  /RTCu - 报告使用了未初始化的变量 当访问未初始化的变量时,此选项将会发出警告。测试 6 包含三个子测试,代码如下:

  void Test6(int value){ int uninitialized; int var; switch (value) { case 3: uninitialized = 4; case 2: var = 5 * uninitialized; break; case 1: int *var2; var2= uninitialized; var = 5 * uninitialized; break; }}

  (请注意,执行 case 3 中的语句后,程序将直接转到 case 2 中执行。)使用以下命令编译此代码:

  cl /Od /MLd /ZI /EHsc /RTCu p

  运行 gs-rtc 6 2 时,系统将显示以下对话框:

  图 5. 使用 gs-rtc 6 2 时所生成的错误

  运行 gs-rtc 6 3 时,系统将不显示对话框,因为变量已被初始化。"但是,即使使用了未初始化的变量,gs-rtc 6 1 也不会出现错误,因为编译器不跟踪可以通过指针来初始化的变量。

  查看本文来源

脑缺血性疾病的临床分类
脑中风后遗症的护理措施
属于血瘀胸痹特点是
标签

友情链接