Debugger error - scope stack underflow
BlitzMax Forums/BlitzMax Programming/Debugger error - scope stack underflow
| ||
I have a piece of code that seems to run fine without debug on, but with debug it gives 'Scope stack underflow'. Any ideas? The code is large... |
| ||
You're doing something you shouldn't be doing? Without some kind of mind reading abilities (or the source code) no one can give you an accurate answer. |
| ||
Usually I would agree with you, but as this is an unusual error that doesn't seem to pinpoint where it's coming from. I thought someone may come up with something like 'I had this error... turned out to be I was doing <whatever>'. This could give me a clue before I have to spend ages stripping the example down to something postable. |
| ||
http://www.blitzbasic.com/Community/posts.php?topic=63181 Any help? |
| ||
From debugger.stdio.bmx :Function OnDebugLeaveScope() GCSuspend If Not scopeStackTop DebugError "scope stack underflow" If currentScope.scope[DEBUGSCOPE_KIND]=DEBUGSCOPEKIND_FUNCTION funcLevel:-1 scopeStackTop:-1 If scopeStackTop currentScope=scopeStack[scopeStackTop-1] Else currentScope=New TScope EndIf GCResume End Function Scopestacktop seems to be a private global. I have no idea what its for so would really need Mark to explain what's happening. From the link Gfk posted, Mark needs sample code. I would suggest adding profile information to output enter/exit functions to narrow down where the problem is. |
| ||
Thanks, fellows. I'm not really any the wiser, so I guess it will be a complete strip required. I am using callbacks with an external dll, though, so maybe that's something to do with it. |
| ||
I am using callbacks with an external dll, though, so maybe that's something to do with it. I *think* (somebody correct me if this is wrong) I remember having to write "win32" after a certain callback procedure declaration? Like this: Function MycallBack(param:int) "win32" |
| ||
I'll give it a whirl, Peter. The funny thing is, all the dll interaction was up and working fine. I made a bunch of changes and the errors started, but none of that was code interacting with the dll. Are function pointers allowed to point to functions declared within a type? |
| ||
BM is not callback safe. The GC will bomb out when you use Callbacks that can be called asyncronous through an outside application / DLL. But that normally results in a different error and happens in release and debug. |
| ||
Is there a way around that, Dreamora? Will disabling the GC in the callback sort it? |
| ||
You could try if GCSuspend / GCResume work (they seem to be mainly have been added for a potential addition of DLL compile capability). But I wouldn't bet it does, GC driven environments are not meant to be influenced by non managed stuff outside their scope. |
| ||
Arse. Replacing that callback with an empty function stops the crash. Is there any way to implement a callback in Max that plays nice? This is a real pain in the nether regions. Mark....Skid....? |
| ||
Nope there isn't As mentioned, the GC is not callback / thread safe. Just don't do it ... What exactly are you trying to achieve? Depending on that there might be a different way to do it thats more appropriate. |
| ||
It's more likely the stack is being corrupted due to incorrect calling conventions or object corruption. If Blitzmax wasn't callback safe it would be more useless than a useless thing, I certainly wouldn't have got hooked on it. If the dll invokes callbacks from threads other than the original caller (audio engines would possibly prefer it) then it should be specifically documented as such as it will trip up any non threaded environment not just max. |
| ||
I agree with Skid. If I get bizarre errors like this, incorrect calling conventions or incorrectly passed pointers are always the first thing I look for. |
| ||
I'm trying to do some 'on the fly' audio creation using fmod streaming. Thanks for the suggestions. I'll just have to keep on digging. |
| ||
Well on a single core you might not run into problems or if your DLL doesn't run in its own thread (defeats the point of using a DLL that is meant to bypass BMs incapability of asyncron / streaming handling of data / streams), then the callbacks might not be a problem. But I would guess the chances are dropping drastically that you'll find enough single cores in the future to please this requirement. It would be simpler if there was a NoGC flag for functions which tell the GC not to touch it at all unless GCCollect is called. Some of that might somewhere in the future be solved when a multi process system or alike is present. |
| ||
Okay... managed to cut out a lot of the rubbish and produce a small example. Graphics 800,600,32,0 Global tonelisthead:tone=Null Global tonelisttail:tone=Null Type tone Const slider_width=700 Global n_tones=0 Const dt#=1.0/44100.0 Field channel=0 Field amp#=0 Field freq#=0 Field phi# Field dphi# 'Field amp_slider:sg_slider 'Field freq_slider:sg_slider Field _next:tone=Null Function Create:tone() newtone:tone=New tone n_tones:+1 If tonelisthead tonelisttail._next=newtone tonelisttail=newtone Else tonelisthead=newtone tonelisttail=newtone EndIf Return newtone End Function Method setfreq(freq#) Self.freq=freq Self.dphi=360.0*Self.freq*dt End Method End Type Const tonesmax=2 For n=1 To tonesmax mytone:tone=tone.Create() mytone.setfreq(60.0) mytone.amp=30000.0 mytone.channel=(n-1) Mod 2 Next Function makesignedshort:Short(float_num#) x=Long(float_num) val_bits:Short=Short(x&%0111111111111111) sign_bit:Short=Short((x Shr 16)&%1000000000000000) short_val:Short=Short(sign_bit|val_bits) Return short_val End Function Function FMOD_Stream_Callback(stream:Byte Ptr, buff:Byte Ptr, length:Int, userdata:Byte Ptr) "Win32" tonal:tone=tonelisthead While tonal tonal.setfreq(60.0) tonal=tonal._next Wend Local snd_ptr:Short Ptr=Short Ptr(buff) For n=0 To (length/4)-1 Local left_float#=0.0 Local right_float#=0.0 tonal:tone=tonelisthead While tonal If tonal.channel=0 left_float:+tonal.amp*Sin(tonal.phi) Else right_float:+tonal.amp*Sin(tonal.phi) EndIf tonal.phi:+tonal.dphi tonal=tonal._next Wend '32767 snd_ptr[0]=makesignedshort(left_float) 'Left speaker snd_ptr[1]=makesignedshort(right_float) 'Right speaker snd_ptr:+2 Next tonal:tone=tonelisthead While tonal tonal.phi:Mod 360.0 tonal=tonal._next Wend Return 1 End Function Local CallbackPtr=Int(Byte Ptr(FMOD_Stream_Callback)) ?Mac FSOUND_SetOutput(FSOUND_OUTPUT_MAC) ? FSOUND_SetDriver(0) If Not FSOUND_Init(44100, 16, 0) Print "error" EndIf Local stream= FSOUND_Stream_Create(CallbackPtr, 6*2048, FSOUND_NORMAL|FSOUND_16BITS|FSOUND_STEREO, 44100, Null) FSOUND_Stream_Play(FSOUND_FREE, stream) If (FSOUND_Stream_Play(FSOUND_FREE, NSFStream) = -1) Print("Error!") EndIf finished=0 Repeat Cls DrawText "test",100,100 Flip Until KeyHit(KEY_ESCAPE) FSOUND_Stream_Close(stream) FSOUND_Close() End I would really appreciate if anyone can come up with any suggestions, or better still, if you have fmod installed or are prepared to install it, give it a run. This should produce a continuous 60Hz tone generated on the fly. With debug switched on I'm getting the dreaded scope stack error. This is stumping me, because as I said, this was up and working before I added some unrelated stuff to the project (working on the gui), now even this short example seems fragged. From what I read, FMOD is only single threaded, so there shouldn't be a problem there. |
| ||
Hmm, im using fmod 3.74 (the only one i could find) so this might be because of that. For me it just exits after 1/2 second without making a sound. No debug error. Then again, without debug i get no sound either. sooo.. But when adding a debuglog on enter/exit i get : setMemBit error: membit already set on this line: While tonal If tonal.channel=0 <------ left_float:+tonal.amp*Sin(tonal.phi) Else If there is a newer module, could someone point me in the right direction? EDIT: if i add the NoDebug directive to the callback, i get the stack underflow error after a few runs of the function. |
| ||
Hey thanks a lot for your help, Grable. I'm not sure what's going on here. fmod 3.74 is what I'm using, but I do get a sound played, and it doesn't seem to crash with debug off. Is your setup of fmod definitely calling the callback? Stick a drawtext in the fmod_stream_callback function if you're not sure. This would give some confidence that fmod is at least partially doing what it should. I'm assuming you're on XP (as I am)? The setmembit error could be a lead although I don't get that. I'm guessing its something to do with the garbage collector. |
| ||
It is called, as the DebugLogs at enter/exit prints what they should. Changing code and calling other functions from within the callback causes random crashes and errors. This is usually how i know i have messed up calling conventions, ie the stack is totaly screwed or the GC is misbehaving. But it might also be my version of the module is somehow trashed, as i should be able to get sound in non debug mode like you. I have tested it with other minor examples without trouble though :/ Oh, yeah im on XP as well. |
| ||
If you only have headphones or a small speaker, try upping the frequency from 60.0<tonal.setfreq(60.0)> as maybe you won't hear something that low. No idea regarding the crashes you are seeing though. I think it's unlikely your module is trashed if you've had working examples. |
| ||
If you only have headphones or a small speaker, try upping the frequency from 60.0<tonal.setfreq(60.0)> as maybe you won't hear something that low Yeah, i have some cheap'o mini speakers so that did it ;) |
| ||
I don't have any of the modules required, but i'll take a look on the weekend if I can. We are using callbacks heavily in Flow and are not suffering problems, literally thousands of times a seconds sometimes. One thing that DOES give us headaches are casting pointers, so that's where i'd look first. I do not like seeing code like "Short Ptr(etcptr)" Because I do not trust them, they've always caused problems for us! I'm not saying not to use, but those are the lines i'd be suspicious of. |
| ||
Dude, I really appreciate your efforts. I promise to Pimp Flow whenever the chance arises! I will go back and take a look myself. |