最高级别的继承

Bac*_*ave 6 .net c# stack-overflow inheritance

我写了一个包含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
Run Code Online (Sandbox Code Playgroud)

我得到了一个StackOverflow异常Class700,但是每次运行它都会改变,但通常大约为700.

任何人都能解释为什么在大约700级时会发生StackOverflow,以及为什么每次运行程序时这都会改变?

我使用的是Windows 8.1 Enterprise 64位.

Han*_*ant 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,但是反措施实施起来非常便宜.