Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何处理或避免C++; C++中,堆栈溢出通常会导致程序的不可恢复崩溃。对于需要真正健壮的程序来说,这是一种不可接受的行为,特别是因为堆栈大小是有限的。关于如何处理这个问题的几个问题_C++_Error Handling_Crash_Stack Overflow - Fatal编程技术网

如何处理或避免C++; C++中,堆栈溢出通常会导致程序的不可恢复崩溃。对于需要真正健壮的程序来说,这是一种不可接受的行为,特别是因为堆栈大小是有限的。关于如何处理这个问题的几个问题

如何处理或避免C++; C++中,堆栈溢出通常会导致程序的不可恢复崩溃。对于需要真正健壮的程序来说,这是一种不可接受的行为,特别是因为堆栈大小是有限的。关于如何处理这个问题的几个问题,c++,error-handling,crash,stack-overflow,C++,Error Handling,Crash,Stack Overflow,是否有一种方法可以通过通用技术防止堆栈溢出。(一个可扩展、健壮的解决方案,包括处理占用大量堆栈的外部库等) 有没有办法在发生堆栈溢出时处理它们?最好是在有处理程序来处理这类问题之前,将堆栈展开 还有一些语言,它们的线程具有可扩展的堆栈。C++中有可能吗? < >对C++行为解决方案的任何其他有用的意见都将被理解。 处理堆栈溢出不是正确的解决方案,相反,您必须确保您的程序不会溢出堆栈 不要在堆栈上分配大变量(其中“大”取决于程序)。确保任何递归算法在已知最大深度后终止。如果递归算法可能会递归未知次

是否有一种方法可以通过通用技术防止堆栈溢出。(一个可扩展、健壮的解决方案,包括处理占用大量堆栈的外部库等)

  • 有没有办法在发生堆栈溢出时处理它们?最好是在有处理程序来处理这类问题之前,将堆栈展开

  • 还有一些语言,它们的线程具有可扩展的堆栈。C++中有可能吗?


  • < >对C++行为解决方案的任何其他有用的意见都将被理解。 处理堆栈溢出不是正确的解决方案,相反,您必须确保您的程序不会溢出堆栈

    不要在堆栈上分配大变量(其中“大”取决于程序)。确保任何递归算法在已知最大深度后终止。如果递归算法可能会递归未知次数或大量次,请自己管理递归(通过维护自己的动态分配堆栈)或将递归算法转换为等效的迭代算法

    一个必须“非常健壮”的程序不会使用“消耗大量堆栈”的第三方或外部库


    请注意,某些平台在堆栈溢出发生时会通知程序,并允许程序处理错误。例如,在Windows上,会引发异常。这个异常不是C++异常,但是它是异步异常。虽然C++异常只能由<代码>抛出语句抛出,但在执行程序时可能会在任何时候抛出异步异常。但这是意料之中的,因为堆栈溢出随时都可能发生:任何函数调用或堆栈分配都可能使堆栈溢出

    问题是,堆栈溢出可能会导致异步异常被抛出,即使是预期不会抛出任何异常的代码(例如,在C++中标记为
    noexcept
    throw()
    的函数)。因此,即使您确实以某种方式处理了这个异常,您也无法知道您的程序处于安全状态。因此,处理异步异常的最佳方法是根本不处理它(*)。如果抛出一个,则表示程序包含错误

    其他平台可能有类似的方法来“处理”堆栈溢出错误,但任何此类方法都可能遇到相同的问题:预期不会导致错误的代码可能会导致错误


    (*)有一些非常罕见的例外情况。

    C++是一种功能强大的语言,伴随着这种能力,你可以向自己的脚开枪。我不知道有任何可移植的机制在堆栈溢出发生时检测和纠正/中止。当然,任何此类检测都是特定于实现的。例如,g++提供了
    -fstack protector
    来帮助监控堆栈使用情况


    一般来说,您的最佳选择是主动避免基于堆栈的大型变量,并小心递归调用。

    您可以使用良好的编程实践来防止堆栈溢出,例如:

  • 非常小心递归,我最近看到了一个由写得不好的递归CreateDirectory函数导致的SO,如果您不确定代码是否100%正常,那么添加保护变量,该变量将在N次递归调用后停止执行。或者最好不要写递归函数
  • 不要在堆栈上创建巨大的数组,这可能是隐藏的数组,就像一个非常大的数组作为类字段一样。使用向量总是更好的
  • 对alloca要非常小心,尤其是当它被放入一些宏定义中时。我见过许多这样的例子,它们都是由于将字符串转换宏放入使用alloca进行快速内存分配的for循环中而产生的
  • 确保堆栈大小是最佳的,这在嵌入式平台中更为重要。若你们的线程做的不多,那个么就给它一个小堆栈,否则就用大堆栈。我知道预订应该只占用一些地址范围,而不是物理内存
  • 这些是我在过去几年中看到的最令人担忧的原因


    对于自动查找,您应该能够找到一些静态代码分析工具。

    Re:可扩展堆栈。您可以通过以下方式为自己提供更多的堆栈空间:

    #include <iostream>
    
    int main()
    {
        int sp=0;
    
        // you probably want this a lot larger
        int *mystack = new int[64*1024];
        int *top = (mystack + 64*1024);
    
        // Save SP and set SP to our newly created
        // stack frame
        __asm__ ( 
            "mov %%esp,%%eax; mov %%ebx,%%esp":
            "=a"(sp)
            :"b"(top)
            :
            );
        std::cout << "sp=" << sp << std::endl;
    
        // call bad code here
    
        // restore old SP so we can return to OS
        __asm__(
            "mov %%eax,%%esp":
            :
            "a"(sp)
            :);
    
        std::cout << "Done." << std::endl;
    
        delete [] mystack;
        return 0;
    }
    
    #包括
    int main()
    {
    int sp=0;
    //你可能想把这个放大很多
    int*mystack=newint[64*1024];
    int*top=(mystack+64*1024);
    //保存SP并将SP设置为新创建的
    //堆叠框架
    __asm_uuuuuuuuuuuuuuuuuuuu(
    “mov%%esp,%%eax;mov%%ebx,%%esp”:
    “=a”(sp)
    :“b”(顶部)
    :
    );
    
    std::cout我认为这不管用。推送/pop esp比移动到寄存器更好,因为你不知道编译器是否会决定使用eax进行某些操作。

    给你:

  • 您自己不会捕获异常\u堆栈\u溢出结构化异常,因为操作系统将捕获它(在Windows的情况下)
  • 是的,您可以安全地从结构化异常(上面称为“异步”)中恢复,这与上面指出的不同。如果您不能,Windows将根本无法工作。PAGE_错误是从中恢复的结构化异常

  • 我不太熟悉Linux和其他平台下的工作方式。

    标准甚至没有提到堆栈,您应该指定目标平台;有几个平台提供了拦截堆栈溢出的方法,甚至可以获得“堆栈溢出警报”当堆栈几乎耗尽时。就我个人而言,我发现堆栈溢出不是可以避免的,而是可以接受的