How can I show a Runtime error?

BlitzMax Forums/BlitzMax Programming/How can I show a Runtime error?

Grey Alien(Posted 2006) [#1]
Hi,

If I run this code in the IDE:

runtimeerror("testing")


in debug mode, a dialog appears saying unhandled exception: 2 but in non-debug mode it just shows 2 on the IDE output window.

However, when running the actual .exes generated by the IDE, no dialog appears at all.

So how can I make a simple windows style error dialog show for when errors occur and I haven't yet initialised the graphics. Do I need a simple windows libary call as nothing seems to do it in BMax?

Thanks in advance.


Grey Alien(Posted 2006) [#2]
OK sorted it, just before I call runtimeerror I have to call Notify("error message") to see it.


DStastny(Posted 2006) [#3]
Here is correct way. It has to do with catching exceptions.

Type  TApplication
	Method Run()
        Graphics 640,480,0
		While Not KeyHit(KEY_ESCAPE)
			Cls
			If KeyHit (KEY_F1)
				RuntimeError "Poop"			
			End If	
			Flip
		Wend
	End Method
End Type


' Main code notice the try catch that whats important

Try
   (New TApplication).Run
Catch  Text:TRuntimeException  
   Notify Text.ToString()
End Try



Doug Stastny


Grey Alien(Posted 2006) [#4]
thanks budman, I'll try that out.


Grey Alien(Posted 2006) [#5]
Budman: hmm, well I use Try Except all the time in Delphi as that catches anything, not just stuff that is Raised (Thrown). However BMax only seems to catch runtime errors that are created with runtimeerror, not just ones that occur due to bugged code for example:

Type  TApplication
	Method Run()
        Graphics 640,480,0
		While Not KeyHit(KEY_ESCAPE)
			Cls
			If KeyHit (KEY_F1)
				Local image=Null
				DrawImage image,0,0
			End If	
			Flip
		Wend
	End Method
End Type


' Main code notice the try catch that whats important

Try
   (New TApplication).Run
Catch  Text:TRuntimeException  
   Notify Text.ToString()
End Try


I've made F1 create a null image then try to draw it. I was hoping that program flow would jump to the catch and return the error but it won't so Try Catch is not a good general protection, it's only good for errors raised by the programmer. But thanks anyway. Any other ideas how I can make a "general" error trap?


DStastny(Posted 2006) [#6]
I am delphi programmer as well. In delphi all exceptions derive from Exception so typicall you might write

try
..
..
except
 on e:exception do ...
end;
[code]

MAX isnt much differnt and you can catch different types of exceptions.  All exceptions in MAX are objects.

You asked how to catch a runtime error :)

To catch all exceptions
[code]
' Here is one i made up
Type EMyException
	Method ToString:String()
		Return "EMyException- Poopie"	
	End Method
End Type
Type  TApplication
	Method Run()
        Graphics 640,480,0
		While Not KeyHit(KEY_ESCAPE)
			Cls
			If KeyHit (KEY_F1)
				RuntimeError "Poop" ' this throws TBlitzException
			End If				
			If KeyHit (KEY_F2)
				Throw "Poopie"	' This throws a string object						
			End If	
			If KeyHit (KEY_F3)
				Throw (New EMyException)	' This throws EMyException						
			End If	
			
			Flip
		Wend
	End Method
End Type


' Main code notice the try catch that whats important

Try
   (New TApplication).Run
Catch  r:TRuntimeException
	Notify "Runtime "+r.ToString()
Catch  e:String
    Notify "Unhandled"+e.ToString()
Catch  d:EMyException
    Notify "Unhandled"+d.ToString()
End Try


You notice it is very similar. Now you can just catch o:Object and attempt to figure out what it is if you need general handler

Hope this helps.

Doug Stastny


Grey Alien(Posted 2006) [#7]
hmm interesting, so for my example above if I change the bottom bit to:

Try
   (New TApplication).Run
Catch  o:Object
   Notify "o dear"
End Try

it works! But I've no idea what the object is so I can get the error string...any ideas? Thanks very much for all your help.


Grey Alien(Posted 2006) [#8]
Aha, it's OK I searched the modules and found TBlitzException which al the other are derived from and so made this code:

Try
   (New TApplication).Run
Catch  o:Object
   If TBlitzException(o) Then Notify TBlitzException(o).ToString()
End Try


This works well. In debug mode I get a proper error message but in non-debug mode it just says "unhandled memory exception" which is a bit of a shame, but better than just bombing.

This is good because I'm having an issue with OpenGL just bombing on another PC and so now I can wrap all the code with this general catch all, compile a debug version, and then see what's going on (I hope).

[edit]OK, tried this line after the notify line:
If TNullObjectException(o) Then Notify("Null Object")

In debug mode, the second notify is shown, but not in non-debug mode. I assume that debug mode must basically be able to show more detailed error messages due to the way the .exe is compiled - oh well.


DStastny(Posted 2006) [#9]
Just so you know, all blitzexceptions devrive from TBlitzexcetpions but....

Throw "Error" is just a string object. So you may want to
have a else condition else Notify o.Tostring.

Glad to have helped.

Doug Stastny


Grey Alien(Posted 2006) [#10]
OK good idea. Of course it still won't trap user-defined error types unless they inherit from TBlitzException.


Grey Alien(Posted 2006) [#11]
Great. I've made a global var called DebugInt that you can set anywhere in your code so that if it crashes unexpectedly, the number is shown so you at least have an idea where it went wrong. We did this for our Client/Server Delphi database application Merlio32 and it was really useful.

' -----------------------------------------------------------------------------
'General error handling
' -----------------------------------------------------------------------------
Function HandleGeneralError(o:Object)
	'This should be called inside the Catch section of a Try/Catch/End Try like this:
	'Try
	'  'some code
	'Catch o:Object
	'  HandleGeneralError(o)
	'  Shutdown()
	'End Try
	
	EndGraphics 'safety to ensure desktop isn't messed up
	ShowMouse() 'make sure user can click on dialog.
	
	'In debug mode, this will display a valid error message.
	'In non-debug mode (final release), this will show a dialog saying "memory execption error"
	'which is better than nothing.
	'In full-screen mode, this will still show a dialog on the desktop after the graphics mode
	'is ended, and when the dialog is clicked, the game will shutdown.
	If TBlitzException(o) Then
		Local Prefix$ = ""
		If DebugInt<> 0 Then Prefix = "("+DebugInt+") "
		Notify Prefix + TBlitzException(o).ToString()
	Else
		'Perhaps a string has been raised? If so, show it.
		Notify o.Tostring()
	EndIf
End Function


Thanks again Budman. Now my framework will be able to give really good debug info back in the event of a crash.