Inconsistent program startup
BlitzMax Forums/BlitzMax Programming/Inconsistent program startup
| ||
The code I'm working on at the moment runs perfectly well 99% of the time, but every so often I'll get an EXCEPTION_ACCESS_VIOLATION error in a random part of the code. The programs not threaded and I'm not doing anything weird in the way I initialise objects/load assets. (Though a lot of the time, the debugger throws the error in some deep part of the blitzmax modules.) I'm on Vista 64bit with a Core i3 and 4 gigs of ram. I've tried rebuilding all modules and it's still happening. Anyone got any ideas what could be causing it? |
| ||
There could be many things causing it. If the code isn't too big, I'd advice posting it here. I once ran into a problem in Blitz3D wherein the program wouldn't just crash to the debugger, but rather would actually crash to a Windows "blitzcc.exe has encountered a problem and needs to close" message. I struggled with that one for ages, even thinking it might be a Blitz bug... But eventually I figured it was an audio problem I hadn't known about, and it was even then my code that was at fault. First rule of Blitz is that if you think it's an unpredictable bug in Blitz... It probably isn't :B |
| ||
There's too much of it to post on the forums, but I've uploaded a cut down version of the project if anyone wants to take a look. I still get the random crash with just this code. https://dl.dropboxusercontent.com/u/2310154/Game.rar |
| ||
get an EXCEPTION_ACCESS_VIOLATION error in a random part of the code I think this can only be caused by something concurrent like threads, timer triggered events or the garbage collector. I recently had the situation that a program crashes at random point as well although I did nothing concurrent. The problem was that I worked with pointers and somehow messed things up so the GC tried to clear a memory area that he was not allowed to. If you're not working with threads and timers check if something could mess with the GC. Concurrent errors are the worst. Especially when they do not appear in debug mode... but that is another story |
| ||
I think this can only be caused by something concurrent like threads, timer triggered events or the garbage collector. What do you mean by timer triggered events? Is there a way to add a function hook to a timer, or do you just literally mean the event that's added to the queue when a timer ticks? I don't think I'm actually using any timers, but I'll double check. I guess maybe the GC is to blame, though I've no idea how to go about proving that. =/ |
| ||
Especially when they do not appear in debug mode... but that is another story That is happening because in debug mode the variables are not collected the same way. The GC keeps them to be able to display the content in the debug tree although in release mode they would have been collected already. If your program runs fine in debug mode there is a great chance that you try to access a non existing variable. |
| ||
If your program runs fine in debug mode there is a great chance that you try to access a non existing variable. The crashes are happening in debug mode - I haven't actually tried running in non-debug mode yet. Every time it's happened since I started this thread, the debugger has stopped somewhere in a bmax module, so I'll start writing down which module and see if that helps narrow the problem down. Up until now I've been looking back to see which part of my code it was and trying to find a fault there. |
| ||
Sometimes the debugger doesn't open the correct file by default when it catches these errors. But if you go to the debug tab and double-click on the last function in the list, that should get you to the last point of where the debugger thought it was at in your program. |
| ||
Sometimes the debugger doesn't open the correct file by default when it catches these errors. But if you go to the debug tab and double-click on the last function in the list, that should get you to the last point of where the debugger thought it was at in your program. Aye, I managed to figure that out earlier.And so, here's a list of which command my code was calling at the time and where the debugger pointed to in the modules, for the last eleven crashes. CreateCanvas (d3d9graphics.bmx) x2 CreateCanvas (linkedlist.bmx) CreateCanvas (max2d.bmx) x2 CreateCanvas (win32maxguiex.bmx) x2 CreateWindow (win32maxguiex.bmx) DesktopHeightMulti (linkedlist.bmx) *see below SetGraphics (d3d9graphics.bmx) x2 DesktopHeightMulti is from a 3rd party module, so as soon as I saw that, I took it out of my code, in case it was the cause - I'm still getting crashes, so I guess it isn't. As best I can tell, in all of those crashes, the issue was an object being null, but it was always an internal object that I didn't even know about, much less access from my code. (In both of the linkedlist.bmx crashes, the list's enumerator was null) All the crashes happened in the same function in my code, so I cut the program down to just that function and, of course, it stopped crashing. So I guess something I'm doing before that point is breaking the garbage collector - I'm currently trying to narrow it down by commenting out bits of code and running it repeatedly, but since the crash is intermittent, this could take a while. Are there any known ways to arse up the GC that I should be looking out for? |
| ||
I had a similar problem when using minib3d. Turns out, I was freeing entities in the delete() method of my types. It was something like thisType TStone Field Entity:TEntity Method New() Entity = CreateCube() End Method Method Delete() FreeEntity Entity End Method End Type Problem was that there was no way of predicting when the GC would collect the object and call Delete(). What was happening was that the Update and Render functions were called before the GC called Delete() and therefore the entity still existed on the render stack, but the GC would call Delete() before the entity was actually rendered causing it to point nowhere and creating an access violation. Don't know if it is your problem, haven't looked too closely at your code and I can't seem to get it to crash, but it is something to consider. One thing to do is look at the debug tab on the right and see what function your code was in before the bmax module was called and cause the crash. Edit: You posted before i finished my reply :) . Which function is the code in when it crashes? It might not be the source of your problem, but trying to figure out what it is trying to do could give us a clue as to where the problem is occurring. |
| ||
Which function is the code in when it crashes? It might not be the source of your problem, but trying to figure out what it is trying to do could give us a clue as to where the problem is occurring. It's the StartGraphics() function in setgfx.bmx |
| ||
You could try the GL graphics module instead of the d3d9, and see if that helps? brl.glmax2d |
| ||
Am I doing something wrong here:Function Splash() Local splash_window:TGadget = CreateWindow(AppTitle$, 0, 0, 407, 424, Null, WINDOW_CLIENTCOORDS | WINDOW_CENTER) Local splash_canvas:TGadget = CreateCanvas(0, 0, 407, 424, splash_window) Local splash_image:TImage = LoadImage("gfx/splash.png") Local splash_start:Int = MilliSecs(), splash_period:Int = 5 * 1000 Local splash_timer:TTimer = CreateTimer(10) Local quitloop:Int = False ActivateGadget splash_canvas Repeat WaitEvent() Select EventID() Case EVENT_TIMERTICK If MilliSecs() - splash_start > splash_period Then quitloop = True EndIf RedrawGadget splash_canvas Case EVENT_KEYUP, EVENT_MOUSEUP quitloop = True Case EVENT_APPTERMINATE, EVENT_WINDOWCLOSE quitloop = True Case EVENT_GADGETPAINT SetGraphics(CanvasGraphics(splash_canvas)) Cls DrawImage splash_image, 0, 0 Flip End Select Until quitloop StopTimer splash_timer FreeGadget splash_canvas FreeGadget splash_window End Function I've got a batch file running my program over and over, so I can check to see if commenting out certain parts stops the crash. All the program does currently is show the splash screen, create the main window & canvas, then exit. To test the batch file, I shortened the delay on the splash screen from 5 seconds to 1/100th of a second and set it away - it ran for over an hour with no crash. When I change the delay back to 5 seconds, it crashed within five minutes. So is there something in that loop that could break the GC if run too many times? |
| ||
Presumably there's an issue with SetGraphics(CanvasGraphics(splash_canvas)) getting called so often, for some reason. Perhaps occasionally it is failing and therefore the graphics object is null, and then Cls or DrawImage falls over. |
| ||
Presumably there's an issue with SetGraphics(CanvasGraphics(splash_canvas)) getting called so often, for some reason. Perhaps occasionally it is failing and therefore the graphics object is null, and then Cls or DrawImage falls over. Surely 10 times a second isn't too often though? Also, it doesn't actually crash in this function, it crashes in a later function. I changed part of that loop to: Case EVENT_TIMERTICK If MilliSecs() - splash_start > splash_period Then quitloop = True Else RedrawGadget splash_canvas EndIf And it ran without crashing for about twenty minutes, so maybe it's an issue with RedrawGadget? On the last pass of that loop, it would call RedrawGadget and then free the canvas, so if RedrawGadget is doing something behind the scenes maybe that's it? Though it has crashed when I've clicked to quit the splash screen early, so I dunno. Between this and the heat, my head is completely done in. I'll leave it running overnight with that latest change and if it's not crashed by the morning, I'll consider it fixed (or as fixed as you can consider a bug you don't understand) and move on. |
| ||
Surely 10 times a second isn't too often though? Indeed not. Still, I would give the OpenGL graphics driver a go too, and see if it makes any difference. If you find it stops crashing using that, then I'd suggest you may have a general dx driver issue? |
| ||
Still, I would give the OpenGL graphics driver a go too, and see if it makes any difference. If you find it stops crashing using that, then I'd suggest you may have a general dx driver issue? Edit: Just ignore me, my brain is fried. I'll give that a shot mate, cheers. |
| ||
I would not call the redrawgadget on a canvas, but update the canvas instead. Try below if that works better. I hope there is no typo, only edited your code. |
| ||
I would not call the redrawgadget on a canvas, but update the canvas instead. Oh you can do it that way? I was just following the example in the docs, thought you had to be "proper" around canvases. |
| ||
No problem in doing so. Actually I use RedrawGadget very very rare, only when the system should redraw the gadget. |
| ||
Make sure you have windows and DX up to date as well as your graphics drivers. Also check you are using the latest BlitzMax and MaxGUI. I still can't get your program to crash on my machine, and I really tried. :) |
| ||
Some years ago I had a similar problem in a program I was developing. Program randomly crashed at some points with an exception access violation. In that time my problem as because of a 3rd party modules usage (in my case, bah.freeimage). [a] http://blitzbasic.com/Community/posts.php?topic=96697#1120361 [/a] It had something to do about Garbage Collector if I remember well... |
| ||
Well, I modified the program so it exits as soon as it creates the main window and left a batch file running it in a loop all night without any crashes. Since I'd made two changes yesterday (opengl drivers and no more redrawgadget), this morning I commented out the opengl drivers and set it away again - it crashed immediately. So I guess it's a directx issue. Thanks for the help everyone. |
| ||
Ok, so the crash goes away if I switch to opengl, but then I had some weirdness with images when I started a new graphics context (and yes, I was setting them to null and reloading them). In the course of faffing around with the two different drivers (d3d9 and gl), I discovered that the following program will crash sooner or later on my pc:SuperStrict Local gfx:TGraphics Local pix:TPixmap = LoadPixmap("smile.jpg") Local img:TImage gfx = CreateGraphics(640, 480, 0, 60, GRAPHICS_BACKBUFFER) SetGraphics(gfx) SetVirtualResolution(640, 480) img = LoadImage(pix) EnablePolledInput() Repeat CloseGraphics(gfx) gfx = CreateGraphics(640, 480, 0, 60, GRAPHICS_BACKBUFFER) SetGraphics(gfx) SetVirtualResolution(640, 480) img = LoadImage(pix) Repeat Cls DrawImage(img, 0, 0) DrawText(GCMemAlloced(), 0, 240) Flip If KeyHit(KEY_ESCAPE) Then End Until KeyHit(KEY_SPACE) Forever But this variation seemingly had no problems: SuperStrict Local pix:TPixmap = LoadPixmap("smile.jpg") Local img:TImage Graphics(640, 480, 0, 60, GRAPHICS_BACKBUFFER) SetVirtualResolution(640, 480) img = LoadImage(pix) Repeat Graphics(640, 480, 0, 60, GRAPHICS_BACKBUFFER) SetVirtualResolution(640, 480) img = LoadImage("smile.jpg") Repeat Cls DrawImage(img, 0, 0) DrawText(GCMemAlloced(), 0, 240) Flip If KeyHit(KEY_ESCAPE) Then End Until KeyHit(KEY_SPACE) Forever Shouldn't the two be functionally identical? |
| ||
This maxgui version of the previous two examples also crashes out for me.SuperStrict Import maxgui.drivers Local win:TGadget = CreateWindow("test", 0, 0, 640, 480, Null, WINDOW_CLIENTCOORDS | WINDOW_TITLEBAR | WINDOW_CENTER) Local can:TGadget Local pix:TPixmap = LoadPixmap("smile.jpg") Local img:TImage can = CreateCanvas(0, 0, 640, 480, win) SetGraphics(CanvasGraphics(can)) SetVirtualResolution(640, 480) img = LoadImage(pix) Repeat FreeGadget(can) can = CreateCanvas(0, 0, 640, 480, win) SetGraphics(CanvasGraphics(can)) SetVirtualResolution(640, 480) img = LoadImage(pix) Local quit:Int = False Repeat PollEvent() Select EventID() Case EVENT_KEYUP Select EventData() Case KEY_ESCAPE End Case KEY_SPACE quit = True End Select Case EVENT_WINDOWCLOSE, EVENT_APPTERMINATE End End Select Cls DrawImage(img, 0, 0) DrawText(GCMemAlloced(), 0, 240) Flip Until quit = True Forever I've completely reinstalled BlitzMax and updated my graphics drivers since I started this thread, so I'm a little lost as to what's causing the problem. |
| ||
Is also the version I posted above crashing all the time for you, where the canvas is not created or systemwide redrawn every loop? |
| ||
Is also the version I posted above crashing all the time for you, where the canvas is not created or systemwide redrawn every loop? If I compile just the example you posted earlier, then no, it doesn't crash. To be clear, I'm not having an issue at all if my program just creates a single graphics context (be it with Graphics, CreateGraphics or CanvasGraphics) it's only when I free up a graphics context and create another that there's a chance it'll crash. I know it might not seem important, but I'd really like to be able to support multiple resolutions (including borderless windows) without writing a seperate configuration app. |
| ||
Dan: When using OpenGL driver are you setting it for shared contexts? |
| ||
Dan: When using OpenGL driver are you setting it for shared contexts? To fix the image weirdness I mentioned in post 24? I've tried that and it fixes the issue, though surely if I'm reloading all images after I switch contexts, that should be enough? |
| ||
I was meaning for this: I free up a graphics context and create another that there's a chance it'll crash. |
| ||
I've been unable to cause a crash when using the gl driver at all - shared contexts or not. The crash issue only seems to exist with the dx driver. Since the image swapping bug (which I have had happen with both drivers now) is fixed by using GLShareContexts, I should just put this all behind me, but I really can't say a bug is fixed unless I know what caused it. Aside from anything else, unless I know the cause, how can I guarantee it won't resurface later? |
| ||
Necroing this (with dark magicks) to say that I ran into it again recently and discovered if you do a SetGraphicsDriver inbetween CloseGraphics and CreateGraphics in the above examples, it seems to fix the problem. So there's a workaround if anyone else ever has this issue. |
| ||
Whenever I would get some obscure error from a previously unaltered and working program (the debugger would point to an OpenGL call that was working fine before), I would rebuild all the code files that I wrote for the program (after turning off "Quick Build" mode in the IDE to make sure it rebuilds everything), then close the IDE and then open it again. This would usually remove the problem. |
| ||
Whenever I would get some obscure error from a previously unaltered and working program (the debugger would point to an OpenGL call that was working fine before), I would rebuild all the code files that I wrote for the program (by turning off "Quick Build" mode in the IDE), then close the IDE and then open it again. This would usually remove the problem. I can recreate this problem with a single source file though, so it's nothing to do with quickbuild. Just to reiterate (and save people chasing back up the thread), this code crashes: SuperStrict Local gfx:TGraphics Local pix:TPixmap = LoadPixmap("smile.jpg") Local img:TImage Local counter:Int = 0 SetGraphicsDriver(D3D9Max2DDriver()) gfx = CreateGraphics(640, 480, 0, 60, GRAPHICS_BACKBUFFER) SetGraphics(gfx) img = LoadImage(pix) EnablePolledInput() Repeat CloseGraphics(gfx) gfx = CreateGraphics(640, 480, 0, 60, GRAPHICS_BACKBUFFER) SetGraphics(gfx) img = LoadImage(pix) Cls DrawImage(img, 0, 0) DrawText(GCMemAlloced(), 0, 240) Flip counter = counter + 1 Print counter Until counter = 10000 But this code doesn't: SuperStrict Local gfx:TGraphics Local pix:TPixmap = LoadPixmap("smile.jpg") Local img:TImage Local counter:Int = 0 SetGraphicsDriver(D3D9Max2DDriver()) gfx = CreateGraphics(640, 480, 0, 60, GRAPHICS_BACKBUFFER) SetGraphics(gfx) img = LoadImage(pix) EnablePolledInput() Repeat CloseGraphics(gfx) SetGraphicsDriver(D3D9Max2DDriver()) gfx = CreateGraphics(640, 480, 0, 60, GRAPHICS_BACKBUFFER) SetGraphics(gfx) img = LoadImage(pix) Cls DrawImage(img, 0, 0) DrawText(GCMemAlloced(), 0, 240) Flip counter = counter + 1 Print counter Until counter = 10000 I suspect I should post this in the bug forum now that I can reproduce it consistently. |