How to create a StackOverflowException. And how to figure out where it is happening.

本文通过实例详细解析了栈溢出异常(StackOverflowException)的原因及其处理方法,并演示了如何使用WinDbg进行调试。

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

StackOverflowException.

 

This usually means that you have a recursive call in your code.

A recursion is simply a method that calls itself, causing the stack to overflow and throw the StackoverFlow exception.

 

A simple example:

 

namespace SimpleDemo

{

    class Program

    {

        static void Main(string[] args)

        {

            int i = RecursiveMethod();

        }

 

        private static int RecursiveMethod()

        {

            return RecursiveMethod();

        }

    }

}

 

Here it is fairly easy to see what is calling itself and thus being simple to fix.

However, sometimes it is not as clear. It can be a event that triggers itself or an exception that is triggering a new exception of the same kind.

Another simple example that demonstrates an exception that causes a new exception which leads to recursion and failure:

 

namespace StackOverflowDemo

{

    class Program

    {

        static void Main(string[] args)

        {

            Console.WriteLine("Any key to crash");

            Console.ReadLine();

 

            List<Person> persons = new List<Person>();

            persons.Add(new Person { Age = 30, Name = "Paul Paulson" });

            persons.Add(new Person { Age = 10, Name = "John Johnson" });

            persons.Add(new Person { Age = 20, Name = "Eric Ericson" });

 

            foreach (Person p in persons)

            {

                try

                {

                    p.GetAge();

                    Console.WriteLine("{0} is {1} years old", p.Name, p.Age);

                }

                catch (ToYoungException tye)

                {  /* Write to log or something similar */ }

            }

        }

    }

 

    class Person

    {

        public int Age { getset; }

        public string Name { getset; }

 

        public int GetAge()

        {

            if (this.Age < 18)

            {

                throw new ToYoungException(this);

            }

            return this.Age;

        }

    }

 

    class ToYoungException : Exception

    {

        public ToYoungException(Person p)

        {

            Console.WriteLine("{0} is too young. Minumum age is 18, {0} is only {1}.", p.Name, p.GetAge());

        }

    }

}

 

Again, not supercomplicated. When checking a persons age to see if they are under aged an exception is thrown. Possibly to send information to a log or something similar.

However, when writing the output the coder has made a mistake and calls the GetAge() method again on an instance of a Person that is under age.

Which again throws the exception and then again triggers a new exception. And you will have the stack overflow.

 

The code is not intended to be best practice or anything. It is just to demonstrate a simple scenario where it is not obvious where it goes wrong.

It could for example be that the classes are in difference assemblies or namespaces etc.

 

One of the problems with StackoverflowExceptions can be found in the documentation.

 

“StackOverflowException Class”

http://msdn.microsoft.com/en-us/library/system.stackoverflowexception.aspx

 

“Starting with the .NET Framework version 2.0, a StackOverflowException object cannot be caught by a try-catch block and the corresponding process is terminated by default.”

 

So it is a bit hard to protect against since the process goes away when the exception occurs.

One way is to simply attach WinDbg to your running process and use the following steps.

 

Once you have attached to the process load the sos.dll:

.load C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll

 

Change the above to match your .Net version and architecture (x64/x86).

Then create a breakpoint on the Stackoverflow exception:

 

!stoponexception -create System.StackOverflowException

 

Then start the process again, F5 or type g.

When the application stops, the debugger will do report something like this:

 

(115c.4d0): Stack overflow - code c00000fd (first chance)

First chance exceptions are reported before any exception handling.

This exception may be expected and handled.

eax=02b6dca8 ebx=0279b39c ecx=02b6dca8 edx=0279d1e8 esi=0279d1e8 edi=0279d1e8

eip=004b0253 esp=00063000 ebp=00063000 iopl=0         nv up ei pl nz na po nc

cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010202

004b0253 57              push    edi

 

So here it clearly shows that we have a stackoverflow. Save a dump to disk for later examination:

 

.dump /ma C:\Dumps\Stackoverflowdump.dmp

 

or investigate directly by running !clrstack.

In my case we can see that the recursion comes from the constructor in ToYoungException (StackOverflowDemo.ToYoungException..ctor)

calling the GetAge method on the Person instance which triggers the exception which triggers the constructor which calls GetAge etc.

 

0:000> !clrstack

OS Thread Id: 0x4d0 (0)

Child SP IP       Call Site

00063000 004b0253 StackOverflowDemo.ToYoungException..ctor(StackOverflowDemo.Person)*** WARNING: Unable to verify checksum for <processname>.exe

00063008 004b0236 StackOverflowDemo.Person.GetAge()

00063014 004b0273 StackOverflowDemo.ToYoungException..ctor(StackOverflowDemo.Person)  

00063028 004b0236 StackOverflowDemo.Person.GetAge()

00063034 004b0273 StackOverflowDemo.ToYoungException..ctor(StackOverflowDemo.Person)  

00063048 004b0236 StackOverflowDemo.Person.GetAge()

00063054 004b0273 StackOverflowDemo.ToYoungException..ctor(StackOverflowDemo.Person)  

00063068 004b0236 StackOverflowDemo.Person.GetAge()

00063074 004b0273 StackOverflowDemo.ToYoungException..ctor(StackOverflowDemo.Person)  

00063088 004b0236 StackOverflowDemo.Person.GetAge()

 

Hope this helps someone.


开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

内容概要:本文系统研究了基于CNN-SVM的卷积神经网络与支持向量机融合的数据分类预测方法,聚焦其在工业故障识别中的应用,提供了完整的Matlab代码实现。通过CNN提取输入数据的深层空间特征,再由SVM进行高精度分类,充分发挥两者优势,有效提升了故障识别的准确性、鲁棒性与泛化能力。该方法特别适用于处理电力系统、机械设备等领域的高维、非线性、强噪声监测数据,在变压器故障诊断、轴承缺陷识别等场景中具有重要应用价值。文档还整合了机器学习、深度学习、图像处理、路径规划、电力系统优化等多个前沿科研方向的技术资源,配套大量Matlab/Simulink仿真案例与Python代码,全面支持科研复现与工程实践。; 适合人群:具备一定编程基础,熟练掌握Matlab或Python语言,从事电气工程、自动化、人工智能、机械故障诊断等相关领域研究的研发人员及高校研究生; 使用场景及目标:① 实现工业设备的状态监测与多类别故障分类;② 深入理解CNN与SVM融合模型的设计原理与工程实现细节;③ 借助所提供的丰富算法案例开展科研复现、模型优化与系统仿真验证; 阅读建议:建议按照文档目录结构系统化学习,结合百度网盘提供的完整代码资源进行动手实践,重点关注CNN特征提取层与SVM分类器之间的数据接口设计与参数调优策略,同时可延伸学习文中涉及的其他智能算法及其在电力系统、信号处理等领域的交叉应用,全面提升科研创新能力。
内容概要:本文围绕“考虑电动汽车灵活性的微网多时间尺度协调调度”展开研究,提出了一种基于Matlab代码实现的优化调度模型。该模型深入挖掘电动汽车作为灵活可控负荷与分布式储能单元的双重潜力,通过构建日前、日内及实时等多时间尺度的协调调度机制,有效应对光伏发电的间歇性与波动性,实现微电网内部功率的动态平衡。研究综合集成了电动汽车集群的有序充放电管理、储能系统协同优化与多种需求响应策略,建立了以系统运行成本最小化、可再生能源消纳最大化及供电可靠性最优化为目标的综合数学模型,并采用Matlab进行仿真求解。结果表明,所提方法能显著平抑功率波动,优化源-荷-储资源的时空配置,提升微电网运行的经济性与稳定性。; 适合人群:电气工程、能源与动力工程、控制科学与工程、电力系统及其自动化等专业的研究生、高校科研人员,以及从事智能电网、微电网规划、电动汽车与电网互动(V2G)技术研发的工程技术人员。; 使用场景及目标:①研究高比例可再生能源接入背景下,含大规模电动汽车的微电网协同优化运行策略;②掌握多时间尺度滚动优化的建模思想与Matlab/Simulink仿真技术;③探索电动汽车聚合商参与电力市场辅助服务的可行路径与效益评估方法; 阅读建议:建议读者结合提供的Matlab代码进行复现与调试,深入理解目标函数构建、约束条件处理及求解器调用等关键技术环节,可尝试引入电池老化模型、用户出行行为不确定性等更贴近实际的因素,以深化研究的实用性与前瞻性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值