C# 如何确定递归方法的堆栈帧大小?

C# 如何确定递归方法的堆栈帧大小?,c#,.net,clr,stack-trace,jit,C#,.net,Clr,Stack Trace,Jit,我希望能够在发生StackOverflow异常之前预测适合堆栈的递归调用的数量。为此,我需要找出堆栈上给定方法调用的“足迹” 有没有一种方法可以通过编程实现这一点?我查看了System.Diagnostics.StackFrame和System.Diagnostics.StackTrace,但找不到任何相关内容 根据经验,使用,我发现足迹在以下方面有很大不同: 32位vs 64位:~22k vs~8k帧(不同的指针大小是否会导致~3x的增加?) 调试vs发布:~22k vs~64k帧(调试构建

我希望能够在发生
StackOverflow
异常之前预测适合堆栈的递归调用的数量。为此,我需要找出堆栈上给定方法调用的“足迹”

有没有一种方法可以通过编程实现这一点?我查看了
System.Diagnostics.StackFrame
System.Diagnostics.StackTrace
,但找不到任何相关内容

根据经验,使用,我发现足迹在以下方面有很大不同:

  • 32位vs 64位:~22k vs~8k帧(不同的指针大小是否会导致~3x的增加?)
  • 调试vs发布:~22k vs~64k帧(调试构建添加了各种特殊的模式边界检查填充+调试工具)
  • 非优化与优化:
    • 调试中约22k对约51k(预期-较少的调试信息)
    • 发行版中有~64k对~51k(真奇怪!可能使用了一些记忆技术?)
  • 调试器附加与未附加:这在jitted代码中产生了多么大的不同!
    • 85k vs 258k-发布,优化
    • 14k对64k-调试、优化关闭
很可能不同版本的.NET也会产生不同的结果

总而言之:

看到堆栈帧大小随这些参数变化如此之大,是否有一种编程方法可以在运行时计算出给定方法的堆栈帧大小


“离线”(手动)怎么样?也许至少对于直接的、发布的、非优化的构建?

为什么不将给定的方法重构为非递归实现,这样就不必担心堆栈被破坏?我会说局部变量的大小,包括返回值和返回地址。当然,类引用只算作指针(32或64位)。如果您的调用位于表达式的中间,也为正在使用的时间变量添加空间。这将是一个最大值,编译器可能会对其进行优化(例如,重用不再使用的变量的内存位置)。@Servy这是一个理论问题,这不是一个迫切需要解决的问题:)我总是在兜帽下摸索时学到一些新的东西——就像我刚才从我的小实验中得到的数据一样。打电话很容易,它是O(log(n))。因为允许更高复杂度的递归算法总是一个错误,并保证早晚会炸毁你的程序。@HansPassant[需要引证]?这听起来像是一个很好的经验法则,但什么在支持它呢?根据你的回答历史,我很确定这句话是有根据的。