【问题标题】:Catch stack overflow exception C# [duplicate]捕获堆栈溢出异常C# [重复]
【发布时间】:2012-09-22 18:14:46
【问题描述】:

可能重复:
How do I prevent and/or handle a StackOverflowException? (C#)
C# catch a stack overflow exception

我有一个用 C# 编写的相当复杂的应用程序(使用 .NET 2.0)。该程序以高度递归的方式处理大量文件,并且在某些客户端它会遇到堆栈溢出异常。该程序非常复杂,我们甚至无法重现该问题 - 甚至在发生问题的客户那里也无法重现。

显而易见的解决方案是修复导致堆栈溢出的代码,但这似乎不太可能 - 我们的代码库有超过 200 万行代码,它们在内存中创建了一个大型递归数据结构。我们不太可能只是偶然发现问题部分。 (无论如何,短期内不会。)

但是,我们的程序也会备份文件并对正在处理的文件进行更改,如果出现异常,它会将所有内容恢复到原始状态。当堆栈溢出异常发生时,进程只是终止,并且此恢复功能没有机会运行,因为无法捕获堆栈溢出。

所以我的问题是:有没有办法在 .NET 2.0 中捕获堆栈溢出异常。我无法托管 CLR,异常是真正的堆栈溢出,而不是由我们的代码引发。能够做到这一点至少让我能够恢复程序终止之前所做的更改。

编辑:请注意,我很清楚堆栈溢出异常是什么以及它有多严重。我不是在寻找寻找建议的建议——这种情况很少发生。我要做的是在磁盘空间有限的环境中恢复客户端数据发生。如果我的程序在恢复操作后死机,我可以接受。

【问题讨论】:

  • 您能否发布一个您当前正在使用的有问题的代码示例。也许您遇到的只是一个简单的逻辑错误或内存泄漏问题
  • 一旦你发现了一个 SO 异常,你打算做什么?您将如何从中恢复?
  • 听起来您迫切需要日志记录。我猜你有一些 try-catch 块正在吸收错误,阻止你找到它。如果你有一个堆栈溢出异常,你不能真正忽略它或在代码中更正它,堆栈溢出通常意味着你用掉了太多空间以至于你不能做任何事情,这是一个你必须修复而不是解决的错误。
  • 这个 SO 问题的第二个答案可能会有所帮助:stackoverflow.com/questions/107735/…
  • 最好是支持原始答案,也许可以在该答案中添加评论以确认其有效,然后将此问题作为该问题的副本关闭。

标签: c# .net exception .net-2.0 stack-overflow


【解决方案1】:

听起来你在说,我有一个修改文件的进程,如果发生错误,它应该恢复文件,但它没有这样做。

如果相同,为什么不使用临时文件,如果操作完成,用临时文件覆盖源文件。如果发生任何未捕获的异常,则说明您拥有未触及(写入方式)的原始文件。

【讨论】:

  • 我们不这样做的原因是有时我们必须处理的文件很大,并且将它们全部备份可能会耗尽所有磁盘空间。 (并非总是如此,只是每隔一段时间——我们谈论的是不同的客户端和不同的文件集。)我们会备份我们修改的文件,如果出现问题,我们会尝试恢复对文件的所有更改。跨度>
  • 这很有趣,因为从编程的角度来看,解决问题的编程将(99.998% 的时间)比更多的驱动器空间更昂贵。
  • 我们的进程经常在磁盘空间有限的虚拟机中运行——这就是我们必须小心的原因。
  • 在这种情况下,如果映射驱动器没有足够的空间(总)抛出异常,否则休眠直到有足够的空间(比如其他一些虚拟机正在临时使用空间)。
【解决方案2】:

我不建议这样做,但您可以使用/F Compiler Switch 在编译图块处设置堆栈大小。默认值为 1MB。 虽然这不是“修复”代码的好方法,但它可以防止那些讨厌的Stack Overflow 消息。

【讨论】:

  • 我认为这行不通 我们的代码会遇到真正的堆栈溢出——无论我们分配多少堆栈,它最终都会用完。正确的解决方法是找到原因,但正如我所说,代码很大而且非常复杂,所以暂时我想先处理更直接的问题。
  • 指向 /F 编译器开关的链接用于 C/C++ 编译器。我找不到 C# 的编译器选项,但如果它是您创建的线程,您可以在线程构造函数 msdn.microsoft.com/en-us/library/5cykbwz4.aspx 中指定它。
  • @DavidYaw——你是对的。那是针对 C++ 的。在 C# 中,如您所说,您可以在 Thread 构造函数中设置堆栈大小。
猜你喜欢
  • 2010-12-08
  • 2020-11-14
  • 2020-11-01
  • 1970-01-01
  • 2010-12-07
相关资源
最近更新 更多