c# - 最大继承级别

标签 c# .net inheritance stack-overflow

<分区>

我编写了一个包含 1000 个类的源文件,所有类都继承自上面的类:

class Program
{
    static void Main(string[] args)
    {
        Class700 class700 = new Class700();            
    }
}
class Class1 { public Class1() { } }
class Class2 : Class1 { public Class2() { } }
class Class3 : Class2 { public Class3() { } }
class Class4 : Class3 { public Class4() { } }
class Class5 : Class4 { public Class5() { } }
//class ClassN : ClassN-1 { public ClassN() { } } where N = 2 to N = 1000

我在 Class700 上遇到 StackOverflow 异常,但是每次运行它时都会发生变化,但通常在 700 左右。

谁能解释为什么在大约 700 级时会出现 StackOverflow,以及为什么每次运行程序时都会发生变化?

我使用的是 Windows 8.1 企业版 64 位。

最佳答案

看到它在 700 处爆炸很难解释,但我们肯定不是在看真正的代码。你只会在自动生成的代码案例中得到这样的东西,当然没有人会手写这样的东西。

但是,是的,使用这样的代码肯定可以实现 SOE。肉眼看不见,但派生类的构造函数总是调用其基类的构造函数。如果您不自己编写,那么编译器将自动生成该调用。一直到 System.Object 构造函数。

构造函数需要多少堆栈空间是您可以通过调试器看到的。只需隔离两个类的代码,创建一个 Class2 对象并在 Class2 和 Class1 构造函数上设置断点。您需要 Debug + Windows + Registers,记下断点命中时 ESP 寄存器的值、堆栈指针。 64 位模式下的 RSP。

对您的代码片段执行相同操作,我得到 0x024C012C 和 0x024C00E4,相差 72 个字节。将其外推到 700 个类,将需要 700 x 72 = 50400 字节。与 SOE 不接近,当您的程序在 32 位代码中消耗 1 兆字节时会爆炸,在使用强制为 x64 的目标平台编译时会消耗 4 兆字节。抖动也有开销,在减去差值之前您无法猜出这个数字。

您可以使用 Editbin.exe 的/STACK 选项增加堆栈的大小。或者创建一个线程,使用允许您设置堆栈大小的构造函数。

是的,它不能很好地重复是正常的。 CLR 实现了多种反恶意软件技术,其中之一是在随机位置启动堆栈。这使得恶意软件非常难以通过缓冲区溢出攻击来利用 .NET 代码。一般而言,这对 .NET 代码来说不太可能构成威胁,使用 stackalloc 的代码并不多,但该对策的实现成本非常低。

关于c# - 最大继承级别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25957029/

相关文章:

c# - 对大量(50~)属性建模的策略

c# - 如何获取 WSHttpBinding 安全属性?

java - java中的隐式向上转型和显式向下转型

javascript - 如何在javascript中继承基类属性并调用基类构造函数?

java - 从 ArrayList 类继承出现问题, 'receiving non-static method can not be referenced in static context' 错误

c# - Linq orderby 文化(丹麦语,æøå)

c# - 使用图像而不是平铺填充纹理画笔

.net - 使用 DataAnnotations 与 WPF 和 Entity Framework 验证数据?

.net - 有没有办法以编程方式提取接口(interface)?

c# - Bitmap.LockBits 中 ImageLockMode 的用途(附代码)