Inconsistent program startup

BlitzMax Forums/BlitzMax Programming/Inconsistent program startup

dan_upright(Posted 2013) [#1]
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?


Adam Novagen(Posted 2013) [#2]
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


dan_upright(Posted 2013) [#3]
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


UNZ(Posted 2013) [#4]
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


dan_upright(Posted 2013) [#5]
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. =/


jsp(Posted 2013) [#6]
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.


dan_upright(Posted 2013) [#7]
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.


Brucey(Posted 2013) [#8]
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.


dan_upright(Posted 2013) [#9]
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?


TomToad(Posted 2013) [#10]
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 this
Type 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.


dan_upright(Posted 2013) [#11]
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


Brucey(Posted 2013) [#12]
You could try the GL graphics module instead of the d3d9, and see if that helps?
brl.glmax2d


dan_upright(Posted 2013) [#13]
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?


Brucey(Posted 2013) [#14]
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.


dan_upright(Posted 2013) [#15]
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.


Brucey(Posted 2013) [#16]
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?


dan_upright(Posted 2013) [#17]
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.


jsp(Posted 2013) [#18]
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.




dan_upright(Posted 2013) [#19]
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.


jsp(Posted 2013) [#20]
No problem in doing so. Actually I use RedrawGadget very very rare, only when the system should redraw the gadget.


TomToad(Posted 2013) [#21]
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. :)


Rixarn(Posted 2013) [#22]
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...


dan_upright(Posted 2013) [#23]
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.


dan_upright(Posted 2013) [#24]
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?


dan_upright(Posted 2013) [#25]
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.


jsp(Posted 2013) [#26]
Is also the version I posted above crashing all the time for you, where the canvas is not created or systemwide redrawn every loop?


dan_upright(Posted 2013) [#27]
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.


GaryV(Posted 2013) [#28]
Dan: When using OpenGL driver are you setting it for shared contexts?


dan_upright(Posted 2013) [#29]
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?


GaryV(Posted 2013) [#30]
I was meaning for this: I free up a graphics context and create another that there's a chance it'll crash.


dan_upright(Posted 2013) [#31]
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?


dan_upright(Posted 2014) [#32]
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.


Kryzon(Posted 2014) [#33]
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.


dan_upright(Posted 2014) [#34]
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.