VS可能会警告可能的堆栈溢出异常吗?

问题描述:

考虑下面的代码(用于演示目的):VS可能会警告可能的堆栈溢出异常吗?

#include <iostream> 

int main() 
{ 
    char pixels[4][1280][720]; // Big enough to cause a stack overflow on my machine 
    for (unsigned int i = 0; i < 4; i++) 
    { 
     for (unsigned int j = 0; j < 1280; j++) 
     { 
      for (unsigned int k = 0; k < 720; k++) 
      { 
       pixels[i][j][k] = i + j + k; 
      } 
     } 
    } 

    std::cout << pixels[2][640][360]; 
    return 0; 
} 

据对this question解答,最大堆栈大小是由Visual Studio设置。

我正确地假设它可以警告用户有关潜在堆栈溢出? (我自己试过,没有得到警告)

PS:我问的唯一原因是因为我看到很多关于SO的问题,可以通过这样的警告来预防(是的,我不知道每个人SO用户使用VS)。

+4

评估复杂的代码以准确地知道它将如何执行而不执行它是圣杯之一。不要期待你的希望。 – 2014-12-04 18:06:42

+1

你的意思是类似于GCC'-Wstack-usage = 1234'吗? – Fanael 2014-12-04 18:08:08

+2

@Fanael我的意思是如果数组的大小以字节为单位大于堆栈限制,此时堆栈溢出将发生。所以它可能会对此提出警告。是的,似乎是这样。 – Borgleader 2014-12-04 18:09:47

它已经这样做,在有可用的/analyze标志的版本:

C:\>cl /EHsc /analyze stack.cpp 
Microsoft (R) C/C++ Optimizing Compiler Version 18.00.21005.1 for x64 
Copyright (C) Microsoft Corporation. All rights reserved. 

stack.cpp 
c:\stack.cpp(3) : warning C6262: Function uses '3686412' bytes of stack: exceeds /analyze:stacksize '16384'. Consider moving some data to heap. 

prefast工具随DDK/WDK产生了类似的警告。

当然,这是一个非常简单的静态检查(如果函数的堆栈使用率高于某个阈值)。它不会尝试检测递归调用或通过调用链来增加总静态使用量。

+0

是否仅在$ 2,000版本中提供分析? – 2014-12-05 00:43:32

+3

我相信以前的版本是这种情况,但从2013年起[所有版本都有](http://blogs.msdn.com/b/hkamel/archive/2013/10/24/visual-studio-2013 -static码分析纵深 - 什么 - 和 - how.aspx时)。 – 2014-12-05 00:44:42

编译器可以给予警告的几乎所有的,但在这种情况下,这将是非常困难的编译器给一个真正有意义的警告

特别是,堆栈大小直到链接时间才被真正选中。编译器在链接器之前运行,所以它基本上不可能知道在运行链接器时可能选择的堆栈大小。因此,如果编译器发出警告,最好能做的就是假设将选择一些“合理”的堆栈大小,并将警告基于违反该警告。

一个足够智能的链接器可能大概会发出这样的警告,但它需要相当多的智能。特别是,通过链接看到它的时候,堆栈分配看起来像(机器代码表示):

sub esp, 123456 ; or sub rsp, 123456 in 64-bit code. 

链接器必须找到每个堆栈指针是被操纵的地方,并检查涉及的数量的大小以有意义地发出警告。要做到这一点,基本上必须弄清楚什么是代码和什么是数据,并反汇编和检查代码(但不是数据,这些数据可能会反汇编为无意义的代码)。这可能都是可能的,但可能有点不重要,当然也不在连接器通常所做或所用的各种事物的范围之内。

+0

我不知道是否有一个编译器选项,会警告当一个函数使用过量的堆栈。由于我通常在内联的几个级别使编译器决定在堆栈上放置1000个SIMD值时经常吹动堆栈。 – Mysticial 2014-12-04 19:51:38

+0

看起来像这样:http://msdn.microsoft.com/en-us/library/7yhee2f0.aspx – Mysticial 2014-12-04 19:59:34

+0

@Mysticial:正如Andrew Medico指出的那样,'/ analyze'标志基本上符合我的第二段提示:选择一个“合理”的大小,并警告你,如果超过。大小默认为16K,但您可以根据需要将其设置为其他大小,例如:'/ analyze:stacksize 65535',这显然会寻找64K。 – 2014-12-04 20:02:06