Design Discussion Stack Overflow Exception

Talk nerdy to us here.
Post Reply
User avatar
JunJayMdM
Reactions:
Posts: 262
Joined: April 2nd, 2012, 6:00 pm

Stack Overflow Exception

Post by JunJayMdM » November 28th, 2012, 12:10 pm

I've got this error from my debug :

System.StackOverflowException: The maximum stack depth for the interpreter has been exceeded.

Now, my Try-Catch block is inside Run() and by looking at the IL code, I noticed 2 of my methods indicate a Max Stack of 9.

The interaction was interrupted because I caught the exception, but should I throw it or try to solve the problem? (which I have no clue how :P)
I'm wondering, because if I remove the Try-Catch block, there's no indication of bad behavior and the interaction runs just fine.

I hope you can help me with this :)

User avatar
twallan
Reactions:
Posts: 270
Joined: December 26th, 2011, 6:00 pm

Post by twallan » November 28th, 2012, 12:47 pm


That maximum number of nested function calls allowed by TS3 interpreter is "64". If you exceed that number, the game throws an error.

You need to chop your stack-frame at some point and delay it until such time as the stack-frame is smaller.

It happens a lot with Event Listeners, so in most of my code I use a "DelayedEventListener" class which pushes the event handling onto the Simulator as a One Shot Function Task. That way it does not have the added baggage of the stack-frame from the calling parent.

That only works if you can indeed delay the processing though. If you need to perform it immediately, you will need to cut down on the number of nested functions in use.

User avatar
JunJayMdM
Reactions:
Posts: 262
Joined: April 2nd, 2012, 6:00 pm

Post by JunJayMdM » November 28th, 2012, 12:53 pm

I guess I'll have to go with the second option, cos I can't delay it. It's a pity cos I spent hours refining it, but I can't really help it...

Thanks a lot for the explanation :)

User avatar
JunJayMdM
Reactions:
Posts: 262
Joined: April 2nd, 2012, 6:00 pm

Post by JunJayMdM » November 29th, 2012, 7:30 am

After some investigation, I identified the culprit :

<!-- ws:start:WikiTextCodeRule:0:
<pre class="text">EventTracker.SendEvent(new SocialEvent(EventTypeId.kSocialInteraction, this.Actor, IMSD, &quot;Chat&quot;, false, true, false, CommodityTypes.Undefined));</pre>
-->
<style type="text/css"><!--
/**
* GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann
* (http://qbnz.com/highlighter/ and http://geshi.org/)
*/
.text {font-family:monospace;}
.text .imp {font-weight: bold; color: red;}
.text span.xtra { display:block; }

-->
</style><pre class="text">EventTracker.SendEvent(new SocialEvent(EventTypeId.kSocialInteraction, this.Actor, IMSD, "Chat", false, true, false, CommodityTypes.Undefined));</pre>


This thing overloads the stack, especially since It's fired for each IMSD(IMiniSimDescription) in the list.

I managed to isolate it in a standalone method where I only pass IMSD as argument and the issue seems to have stopped, but I'm still worried about it.

So, my question now is : Do I really need to send this event?

I have no clue what most of the events do in the game, but EA uses this one whenever Sims chat. Also, it's two of them, one for each Sim.
Technically, my interaction doesn't involve "chatting", all the relationships are scanned and action is taken based on different factors.

Any suggestion on this?

User avatar
twallan
Reactions:
Posts: 270
Joined: December 26th, 2011, 6:00 pm

Post by twallan » November 29th, 2012, 1:04 pm


Fire the event asynchronously by creating a one shot function task for it. That way you can still inform the game of your social interaction, and not have to worry about the call overflowing.

<!-- ws:start:WikiTextCodeRule:0:
<pre class="text"> public class Task<br/> {<br/> Sim mActor;<br/> IMiniSimDescription mTarget;<br/><br/> public Task(Sim actor, IMiniSimDescription target)<br/> {<br/> mActor = actor;<br/> mTarget = target;<br/><br/> Simulator.AddObject(new OneShotFunctionTask(OnPerform));<br/> }<br/><br/> protected void OnPerform()<br/> {<br/> EventTracker.SendEvent(new SocialEvent(EventTypeId.kSocialInteraction, mActor, mTarget, &quot;Chat&quot;, false, true, false, CommodityTypes.Undefined));<br/> }<br/> }</pre>
-->
<style type="text/css"><!--
/**
* GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann
* (http://qbnz.com/highlighter/ and http://geshi.org/)
*/
.text {font-family:monospace;}
.text .imp {font-weight: bold; color: red;}
.text span.xtra { display:block; }

-->
</style><pre class="text"> public class Task
{
Sim mActor;
IMiniSimDescription mTarget;
&nbsp;
public Task(Sim actor, IMiniSimDescription target)
{
mActor = actor;
mTarget = target;
&nbsp;
Simulator.AddObject(new OneShotFunctionTask(OnPerform));
}
&nbsp;
protected void OnPerform()
{
EventTracker.SendEvent(new SocialEvent(EventTypeId.kSocialInteraction, mActor, mTarget, "Chat", false, true, false, CommodityTypes.Undefined));
}
}</pre>


User avatar
JunJayMdM
Reactions:
Posts: 262
Joined: April 2nd, 2012, 6:00 pm

Post by JunJayMdM » November 29th, 2012, 1:29 pm

Oooh that's fancy XD

This stuff is a bit out of my league though, so I got as far as doing this in my loop :

<!-- ws:start:WikiTextCodeRule:0:
<pre class="text">//start iteration<br/>//.....<br/>PlumbBookHandler.Task task = new PlumbBookHandler.Task(this.Actor, IMSD);<br/>//.....<br/>//end iteration<br/></pre>
-->
<style type="text/css"><!--
/**
* GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann
* (http://qbnz.com/highlighter/ and http://geshi.org/)
*/
.text {font-family:monospace;}
.text .imp {font-weight: bold; color: red;}
.text span.xtra { display:block; }

-->
</style><pre class="text">&nbsp;
//start iteration
//.....
PlumbBookHandler.Task task = new PlumbBookHandler.Task(this.Actor, IMSD);
//.....
//end iteration
&nbsp;</pre>


Is instantiating enough to make it work? Should I also worry about destroying those objects created?

Sorry for all these questions, I'm still learning :)

User avatar
twallan
Reactions:
Posts: 270
Joined: December 26th, 2011, 6:00 pm

Post by twallan » November 29th, 2012, 1:49 pm


Actually just doing this is sufficient:

<!-- ws:start:WikiTextCodeRule:0:
<pre class="text">...<br/>new PlumbBookHandler.Task(this.Actor, IMSD);<br/>...</pre>
-->
<style type="text/css"><!--
/**
* GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann
* (http://qbnz.com/highlighter/ and http://geshi.org/)
*/
.text {font-family:monospace;}
.text .imp {font-weight: bold; color: red;}
.text span.xtra { display:block; }

-->
</style><pre class="text">...
new PlumbBookHandler.Task(this.Actor, IMSD);
...</pre>


You don't need to store the task in a local field, since you don't need to do anything with it later.

One Shot Function Tasks automatically remove themselves from the simulator once the Function is complete, that is their purpose. :)

User avatar
JunJayMdM
Reactions:
Posts: 262
Joined: April 2nd, 2012, 6:00 pm

Post by JunJayMdM » November 29th, 2012, 1:55 pm

Awesome, I didn't think it was that simple, I was going mad looking in EA code to find asynchronous stuff but all I found was synchronous, while articles around talked about delegates and invoking :P

I'll add the other event too in the task, I don't want to offend EA XD

Thanks a lot, as usual, I wouldn't know what to do without your help :)

Post Reply