【问题标题】:C++ Run-time Preempting Stack-OverflowsC++ 运行时抢占堆栈溢出
【发布时间】:2018-01-28 23:50:27
【问题描述】:

我正在尝试编写一个可以解析最终用户文件的库,用于将一些简单的用户生成的内容添加到项目中,并且我想尝试使该库尽可能灵活。我将递归用于“对象”的标记化过程,该过程通过四个函数链,但我与如何处理最终用户高兴嵌套对象的潜在情况相冲突。我知道我可以对程序可以递归的次数设置一个硬性限制,但我想让它尽可能灵活。有什么方法可以计算出这个进程可以执行的(最大 - 1)次,这样我就可以抢占堆栈溢出错误并返回一个错误或要处理的东西?

【问题讨论】:

  • 任何递归都可以重写为迭代加显式堆栈。这样您就不受调用堆栈大小的限制,而仅受系统上可用内存的限制。
  • C++ 标准没有指定确定递归函数调用所需的可用堆栈空间的方法,也没有指定进程可用的堆栈空间量。
  • @IgorTandetnik 这听起来很有趣,也是一个不错的选择。链中的函数执行一些检查和一些这样的检查,并将信息返回到链中。您能否指出任何有关可能实现的教程或文章?

标签: c++ recursion memory stack-overflow


【解决方案1】:

有什么方法可以计算这个[递归]过程可以执行的(最大 - 1)次...

没有。甚至不能保证调用链中每个栈帧的大小都是一样的。

将递归实现转换为迭代实现相当简单且定义明确:您只需

  1. 用显式状态容器替换隐式调用堆栈(和函数调用操作),例如std::stack<State>
  2. 不是递归调用,而是将新调用的 State 压入堆栈,然后继续循环
  3. 循环没有被调用,而是从堆栈中弹出当前的State 开始并处理它,如果您之前已经进行了另一个递归调用,这可能需要在此处推送另一个新的State

或者,您可以将当前的递归下降解析器拆分为标记器和 LALR(或类似)解析器,它们首先都是迭代的。例如,您可以使用 Flex 和 Bison (Lex/Yacc) 生成这些。

【讨论】:

    【解决方案2】:

    在 Windows 上,您可以使用 SEH 框架通过 __try/__except 捕获堆栈溢出异常并退出您的程序。
    但是,如果您的应用程序使用 C++,那么您需要使用 /EHa 或 /EHsc 标志进行编译。 查看此链接以了解有关在 C\C++ 中使用 SEH 的更多详细信息以及使用 /EHa 和 /EHsc 标志的细节。
    https://docs.microsoft.com/en-us/cpp/cpp/structured-exception-handling-c-cpp

    __try  
    {  
        //code which might generate stack overflow  
    }  
    __except(EXCEPTION_EXECUTE_HANDLER)  
    {  
        //handle stack overflow exception, throw error and exit program     
    } 
    

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-28
      • 2013-09-11
      • 2012-12-20
      • 2011-03-02
      • 2014-01-17
      • 1970-01-01
      相关资源
      最近更新 更多