最高级别的继承

时间:2014-09-21 07:47:05

标签: 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 Enterprise 64位。

1 个答案:

答案 0 :(得分:5)

在700处看到炸弹很难解释,但我们肯定不会看真实的代码。你只能在自动生成的代码中得到类似的东西,当然没有人会手写这样的东西。

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

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

对你的代码片段做同样的事情,我得到0x024C012C和0x024C00E4,相差72个字节。将其外推到700个类,需要700 x 72 = 50400个字节。不接近SOE,你的程序在32位代码消耗1兆字节时炸弹,在目标平台强制使用x64时编译4兆字节。抖动也有开销,这是你无法猜测的数字,直到你减去差异。

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

是的,它不重复是正常的。 CLR实现了几种反恶意软件技术,其中一种技术是在随机位置启动堆栈。这使得恶意软件利用缓冲区溢出攻击来利用.NET代码变得非常。对于一般的.NET代码来说,这是一个非常不可能的威胁,而不是使用stackalloc的很多代码,但反措施实施起来非常便宜。