How does Try/Catch work?

BlitzMax Forums/BlitzMax Programming/How does Try/Catch work?

Russell(Posted 2008) [#1]
I'm new to this aspect of error detection, so bare with me.
I have a program that needs to read some data from disk into a data structure. I want to be able to catch a file error such as reading beyond the end of the file, etc, so I thought I could put the ReadShort()s/ReadLong()s, etc inside a Try/Catch block and I could nab an error before it causes major problems. Take a look at the following test code:
t:TStream = WriteStream("testfile.bla")
WriteLong(t,20000)
WriteLong(t,30000)
CloseStream(t)

Try
	u:TStream = OpenStream("testfile.bla")
	a:Long = ReadLong(u)
	b:Long = ReadLong(u)
	c:Long = ReadLong(u)   ' Does not cause an error!
	d:Long = ReadLong(u)  ' Neither does this!
Catch err:TStreamReadException
	If err <> Null Then End  ' This line is never executed
EndTry

Print a
Print b
Print c
Print d
CloseStream(u)

The third and fourth Readxxxx() lines simply return zero (which I suppose could be handy in some situations), so how can I distinguish between an error zero and a legitimate value of zero read from the file?

According to the docs, if ReadShort() etc can not read enough data, they throw a TStreamReadException error. So how do I 'catch' that error and act accordingly?

Thanks,
Russell


plash(Posted 2008) [#2]
Something doesn't seem right here...

For a better example on how to use Try/Catch:
SuperStrict

Framework brl.standardio
Import brl.stream

Try
	
	Throw New(TStreamReadException)
	
Catch e:Object
	
	Print e.ToString()
	End
	
End Try

End



Grey Alien(Posted 2008) [#3]
so bare with me
Much as I like this forum, I'm not getting naked.


markcw(Posted 2008) [#4]
This should help
http://www.cplusplus.com/doc/tutorial/exceptions.html


Brucey(Posted 2008) [#5]
You example doesn't raise an exception because EOF has been reached after the second ReadLong().

This causes, internally, ReadBytes() to return 8, and not throw an exception.
One way to get the execption is to ReadInt() on the second read, and then on the third, ReadLong().

One might consider this a bug, since now you have reached EOF, you can keep "reading" without error.
Then again, perhaps you are meant to check EOF after every read.
But supposedly, you might also consider that an exception would be thrown if you tried to read past the end of the file - if EOF was true or not.

But Try/Catch in BlitzMax generally works well. You can even throw them from C/C++, which is cool :-)


Russell(Posted 2008) [#6]
Slightly clearer than muddy water, but...

So I have to 'Throw' the error-potential for it to be caught (using Plash's example)? I'll have a look-see at your example.

So does anyone have a tried-and-true method for safely reading large files that may have been corrupted (and therefore are not the size they should be)?

Thanks
Russell


plash(Posted 2008) [#7]
So I have to 'Throw' the error-potential for it to be caught (using Plash's example)? I'll have a look-see at your example.
Uh, no. That's not what I intended, I was just trying to show you how it works. You can just accept the exception as an object and type-cast it to figure out which kind of stream error it is.


Russell(Posted 2008) [#8]
Thanks Plash.

I don't get why reading past the end of the file doesn't cause any errors, though. I have an idea for another method, but Try/Catch may still have a use if I can get to work the way I want.

Russell


Gabriel(Posted 2008) [#9]
I don't get why reading past the end of the file doesn't cause any errors, though

Because your read requests use up precisely the amount of data available. You wrote two longs, and you read two longs. At this point, it makes a note that the the end of the file has been reached. On future reads, it does not attempt to read anything because it knows it reached the end of the file. It doesn't try to read, so there can be no error.


plash(Posted 2008) [#10]
On future reads, it does not attempt to read anything because it knows it reached the end of the file. It doesn't try to read, so there can be no error.
Yes, but it should throw the exception to tell you it is out of data.


Brucey(Posted 2008) [#11]
Yes, but it should throw the exception to tell you it is out of data.

Indeed.

It should at least be consistent.


Gabriel(Posted 2008) [#12]
Yes, but it should throw the exception to tell you it is out of data.

If you mean it should be rewritten to ensure that it does do that, I agree, it should. It's very random to behave differently depending on whether it runs out of data in the middle of an operation or at the end of one.


Russell(Posted 2008) [#13]
Well, Try/Catch doesn't work as I would expect it to. I was hoping it would work like other language's OnError libraries (such as Purebasic's, although it is only in the Windows version):
Procedure ErrorHandlingFunction()
   blah blah blah
EndProcedure

OnError(@ErrorHandlingFunction)

..and then any errors that occur will call the function automagically :) Try/Catch seems to require me to throw the error instead of Bmax? Weird.

Anyway, I found another way to do it. But OnError() would be quite handy (and easier to use).

Russell