digitalmars.D.learn - Exception Safe Programming
- "Saaa" <empty needmail.com> Feb 24 2007
- "Jarrett Billingsley" <kb3ctd2 yahoo.com> Feb 24 2007
- "Saaa" <empty needmail.com> Feb 24 2007
- Tyler Knott <tywebmail mailcity.com> Feb 24 2007
- "Saaa" <empty needmail.com> Feb 25 2007
- renoX <renosky free.fr> Feb 25 2007
- "Saaa" <empty needmail.com> Feb 25 2007
- Frits van Bommel <fvbommel REMwOVExCAPSs.nl> Feb 25 2007
- "Saaa" <empty needmail.com> Feb 25 2007
- Frits van Bommel <fvbommel REMwOVExCAPSs.nl> Feb 25 2007
- "Saaa" <empty needmail.com> Feb 25 2007
- Tyler Knott <tywebmail mailcity.com> Feb 25 2007
- "Saaa" <empty needmail.com> Feb 25 2007
- Tyler Knott <tywebmail mailcity.com> Feb 25 2007
- "Saaa" <empty needmail.com> Feb 25 2007
- Tyler Knott <tywebmail mailcity.com> Feb 25 2007
- "Saaa" <empty needmail.com> Feb 25 2007
- Daniel Keep <daniel.keep.lists gmail.com> Feb 25 2007
- Manfred Nowak <svv1999 hotmail.com> Feb 25 2007
- "Saaa" <empty needmail.com> Feb 25 2007
- "Saaa" <empty needmail.com> Feb 25 2007
- Tyler Knott <tywebmail mailcity.com> Feb 25 2007
- "Saaa" <empty needmail.com> Feb 26 2007
On the website there is the following example:
Transaction abc()
{
Foo f;
Bar b;
f = dofoo();
try
{
b = dobar();
return Transaction(f, b);
}
catch (Object o)
{
dofoo_undo(f);
throw o;
}
}
When f=dofoo() is run and doesn't succeed I suspect that f hasn't changed
and dofoo has thrown an exception.
Because of the exception the try part isn't run, but the catch part is.
Did I understand this correctly?
The explanation of the try statement on the website is not the most
comprehensible one (^.^)
Feb 24 2007
"Saaa" <empty needmail.com> wrote in message news:erqh38$2hen$1 digitalmars.com...On the website there is the following example: Transaction abc() { Foo f; Bar b; f = dofoo(); try { b = dobar(); return Transaction(f, b); } catch (Object o) { dofoo_undo(f); throw o; } } When f=dofoo() is run and doesn't succeed I suspect that f hasn't changed and dofoo has thrown an exception. Because of the exception the try part isn't run, but the catch part is. Did I understand this correctly?
Nope. If "f = dofoo()" fails and an exception is thrown, that catch block is not run, because "f = dofoo()" is outside the try block. A catch block is only run if an uncaught exception occurs in the try block right before it. Since "f = dofoo()" is not in a try block, any exception from it will just be thrown out of abc().
Feb 24 2007
That is exactly what I originally thought, but why then is that piece of code a example of how to ... oh wait... if f=dofoo() fails, f is still unchanged and the correct thing to do is to exit the function through an exception. never mind, but thanks :)Nope. If "f = dofoo()" fails and an exception is thrown, that catch block is not run, because "f = dofoo()" is outside the try block. A catch block is only run if an uncaught exception occurs in the try block right before it. Since "f = dofoo()" is not in a try block, any exception from it will just be thrown out of abc().
Feb 24 2007
Saaa wrote:That is exactly what I originally thought, but why then is that piece of code a example of how to ... oh wait... if f=dofoo() fails, f is still unchanged and the correct thing to do is to exit the function through an exception. never mind, but thanks :)
When an exception is thrown and not caught, the compiler unwinds the callstack until it finds a handler. What this means is that if a function throws an exception then the program will look for the closest call inside a try block with a following catch block that will accept the type of the exception (or a type the exception is implicitly castable to). So, for example: import std.stdio; class MsgClass { this() { writefln("MsgClass constructed."); } ~this() { writefln("MsgClass destructed."); } } class TestException : Exception { this(char[] msg) { super(msg); } } void thrower() { writefln("Throwing exception."); throw new TestException("This is an exception"); } int inBetween() { //Destructs after the exception because its scope is destroyed by the exception scope MsgClass i = new MsgClass(); thrower(); writefln("Returning 5..."); //Never prints return 5; //Function never returns } void main() { int x; try { x = inBetween(); //x is never assigned } catch(Exception e) { writefln("Caught exception: ", e); } writefln("The value of x is: ", x); //x = 0 } This code will output the following with thrower() called: MsgClass constructed. Throwing exception. MsgClass destructed. Caught exception: This is an exception The value of x is: 0 And this without: MsgClass constructed. Returning 5... MsgClass destructed. The value of x is: 5
Feb 24 2007
Thanks, I understand it now: place 'x = inBetween();' before 'try' and the catch will never run (crash)When an exception is thrown and not caught, the compiler unwinds the callstack until it finds a handler. What this means is that if a function throws an exception then the program will look for the closest call inside a try block with a following catch block that will accept the type of the exception (or a type the exception is implicitly castable to). So, for example: import std.stdio; class MsgClass { this() { writefln("MsgClass constructed."); } ~this() { writefln("MsgClass destructed."); } } class TestException : Exception { this(char[] msg) { super(msg); } } void thrower() { writefln("Throwing exception."); throw new TestException("This is an exception"); } int inBetween() { //Destructs after the exception because its scope is destroyed by the exception scope MsgClass i = new MsgClass(); thrower(); writefln("Returning 5..."); //Never prints return 5; //Function never returns } void main() { int x; try { x = inBetween(); //x is never assigned } catch(Exception e) { writefln("Caught exception: ", e); } writefln("The value of x is: ", x); //x = 0 } This code will output the following with thrower() called: MsgClass constructed. Throwing exception. MsgClass destructed. Caught exception: This is an exception The value of x is: 0 And this without: MsgClass constructed. Returning 5... MsgClass destructed. The value of x is: 5
Feb 25 2007
Saaa a écrit :On the website there is the following example: Transaction abc() { Foo f; Bar b; f = dofoo(); try { b = dobar(); return Transaction(f, b); } catch (Object o) { dofoo_undo(f); throw o; } } When f=dofoo() is run and doesn't succeed I suspect that f hasn't changed and dofoo has thrown an exception. Because of the exception the try part isn't run, but the catch part is. Did I understand this correctly? The explanation of the try statement on the website is not the most comprehensible one (^.^)
That's probably because this is a counter-example, not an example really: more a (convincing) way to show that scope() is much better than try/catch for exception safe programming.. renoX
Feb 25 2007
"renoX" <renosky free.fr> wrote in message news:errs2s$1pvc$1 digitalmars.com...Saaa a écrit :On the website there is the following example: Transaction abc() { Foo f; Bar b; f = dofoo(); try { b = dobar(); return Transaction(f, b); } catch (Object o) { dofoo_undo(f); throw o; } } When f=dofoo() is run and doesn't succeed I suspect that f hasn't changed and dofoo has thrown an exception. Because of the exception the try part isn't run, but the catch part is. Did I understand this correctly? The explanation of the try statement on the website is not the most comprehensible one (^.^)
That's probably because this is a counter-example, not an example really: more a (convincing) way to show that scope() is much better than try/catch for exception safe programming.. renoX
I meant the try statement explanation on http://www.digitalmars.com/d/statement.html#TryStatement
Feb 25 2007
Saaa wrote:"renoX" <renosky free.fr> wrote in message news:errs2s$1pvc$1 digitalmars.com...Saaa a écrit :On the website there is the following example: Transaction abc() { Foo f; Bar b; f = dofoo(); try { b = dobar(); return Transaction(f, b); } catch (Object o) { dofoo_undo(f); throw o; } }
That's probably because this is a counter-example, not an example really: more a (convincing) way to show that scope() is much better than try/catch for exception safe programming..
I meant the try statement explanation on http://www.digitalmars.com/d/statement.html#TryStatement
The only example I see there is: --- int main() { try { try { throw new Exception("first"); } finally { printf("finally\n"); throw new Exception("second"); } } catch(Exception e) { printf("catch %.*s\n", e.msg); } printf("done\n"); return 0; } --- (printf? The horror... :( )
Feb 25 2007
That's probably because this is a counter-example, not an example really: more a (convincing) way to show that scope() is much better than try/catch for exception safe programming..
I meant the try statement explanation on http://www.digitalmars.com/d/statement.html#TryStatement
The only example I see there is: ---
: / I meant the explanation itself.... My question was originally about an example from the exception safe programming page. But I just mentioned that the try statement explanation(on http://www.digitalmars.com/d/statement.html#TryStatement ) isn't the most comprehensible.(for me that is:)
Feb 25 2007
Saaa wrote:That's probably because this is a counter-example, not an example really: more a (convincing) way to show that scope() is much better than try/catch for exception safe programming..
http://www.digitalmars.com/d/statement.html#TryStatement
---
: / I meant the explanation itself....
Ah, I must have read that 'explanation' as 'example'.My question was originally about an example from the exception safe programming page. But I just mentioned that the try statement explanation(on http://www.digitalmars.com/d/statement.html#TryStatement ) isn't the most comprehensible.(for me that is:)
Hmm, yes. That section doesn't seem to explain what exceptions *are*, does it? It seems to assume you already know that. http://www.digitalmars.com/d/errors.html is a bit better, but I'm not sure how clear it is to someone entirely unfamiliar with the concept of exception handling (e.g. someone coming from a purely C background).
Feb 25 2007
Maybe I still don't get it :/
I made this simple function (mostly stolen :)
void getPictureList(char[] dir, out char[][] files){
isdir(dir);
files = std.file.listdir(dir, "*.png");
foreach (d; files)
writefln(d);
writefln(files.length);
//if(files.length < 12) throw new Exception("Not enough images
found(<12)");
}
When I uncomment the last line I get:
Error: pictures: The system cannot find the file specified.
(commented version doesn't generate any errors)
There are only 10 files so an exception should be trown, but not that one !
: )
-
I call the function in my main and at the end of my main there is:
scope(failure)
{
writefln("Press the 'any' key to quit");
getchar();
}
Why isn't this run in the uncommented version?
-
Feb 25 2007
Saaa wrote:Maybe I still don't get it :/ I made this simple function (mostly stolen :) void getPictureList(char[] dir, out char[][] files){ isdir(dir); files = std.file.listdir(dir, "*.png"); foreach (d; files) writefln(d); writefln(files.length); //if(files.length < 12) throw new Exception("Not enough images found(<12)"); } When I uncomment the last line I get: Error: pictures: The system cannot find the file specified. (commented version doesn't generate any errors) There are only 10 files so an exception should be trown, but not that one ! : )
Somewhere in your program you're trying to open a file called "pictures" which is non-existent (at least where the system is looking) causing an exception.I call the function in my main and at the end of my main there is: scope(failure) { writefln("Press the 'any' key to quit"); getchar(); } Why isn't this run in the uncommented version?
Scope guards are excecuted in the reverse order of where they're declared. E.g., using the thrower() function from my last example: void main() { scope(exit) { writefln(); } //newline scope(failure) { writef("scope guards."); //Note: writef (no ln) doesn't add '\n' } scope(failure) { writef("of "); } scope(failure) { writef("an example "); } thrower(); scope failure(failure) { writef("This is "); } } This will print: an example of scope guards.
Feb 25 2007
Saaa wrote:Maybe I still don't get it :/ I made this simple function (mostly stolen :) void getPictureList(char[] dir, out char[][] files){ isdir(dir); files = std.file.listdir(dir, "*.png"); foreach (d; files) writefln(d); writefln(files.length); //if(files.length < 12) throw new Exception("Not enough images found(<12)"); } When I uncomment the last line I get: Error: pictures: The system cannot find the file specified. (commented version doesn't generate any errors) There are only 10 files so an exception should be trown, but not that one ! : )
Somewhere in your program you're trying to open a file called "pictures" which is non-existent (at least where the system is looking) causing an exception.
Yes the dir is 'pictures', but the program runs perfectly with that last line commented out. ? I'd expect it to say: Error: Not enough images found(<12)I call the function in my main and at the end of my main there is: scope(failure) { writefln("Press the 'any' key to quit"); getchar(); } Why isn't this run in the uncommented version?
Scope guards are excecuted in the reverse order of where they're declared. E.g., using the thrower() function from my last example: void main() { scope(exit) { writefln(); } //newline scope(failure) { writef("scope guards."); //Note: writef (no ln) doesn't add '\n' } scope(failure) { writef("of "); } scope(failure) { writef("an example "); } thrower(); scope failure(failure) { writef("This is "); } } This will print: an example of scope guards.
Thanks again. Somehow I keep thinking of scope failure an a property of the scope. But that analogy only works if the scope failure is actually read. I had it at the end of my main (never read :)
Feb 25 2007
Saaa wrote:Yes the dir is 'pictures', but the program runs perfectly with that last line commented out. ? I'd expect it to say: Error: Not enough images found(<12)
Without seeing more of your program I can't tell what's going on. You're right that it should be throwing the "not enough images found" exception, at least based on the snippet you posted. Are you catching the "not enough images found" exception anywhere?
Feb 25 2007
Saaa wrote:Yes the dir is 'pictures', but the program runs perfectly with that last line commented out. ? I'd expect it to say: Error: Not enough images found(<12)
Without seeing more of your program I can't tell what's going on. You're right that it should be throwing the "not enough images found" exception, at least based on the snippet you posted. Are you catching the "not enough images found" exception anywhere?
That is the whole code.. I've stripped it bare. Only a main calling that function: void main() { char[][] files; getPictureList("pictures",files); }
Feb 25 2007
Saaa wrote:That is the whole code.. I've stripped it bare. Only a main calling that function: void main() { char[][] files; getPictureList("pictures",files); }
Ah, I found the problem. You're trying to list the contents of a directory that doesn't exist. The error message isn't very clear, but that's the problem. I don't know why commenting out the line with the throw is changing the behavior of the program, because it shouldn't.
Feb 25 2007
I was that far myself :) It is that I can list everything in that dir when that line is commented out (everything working fine) I too found the error a bit strange, but I thought I shouldn't complain :DSaaa wrote:That is the whole code.. I've stripped it bare. Only a main calling that function: void main() { char[][] files; getPictureList("pictures",files); }
Ah, I found the problem. You're trying to list the contents of a directory that doesn't exist. The error message isn't very clear, but that's the problem. I don't know why commenting out the line with the throw is changing the behavior of the program, because it shouldn't.
Feb 25 2007
Saaa wrote:I was that far myself :) It is that I can list everything in that dir when that line is commented out (everything working fine) I too found the error a bit strange, but I thought I shouldn't complain :DSaaa wrote:That is the whole code.. I've stripped it bare. Only a main calling that function: void main() { char[][] files; getPictureList("pictures",files); }
directory that doesn't exist. The error message isn't very clear, but that's the problem. I don't know why commenting out the line with the throw is changing the behavior of the program, because it shouldn't.
I've had some *really* bizarre problems with some Exceptions lately. I made the huge mistake of upgrading the D compiler when I had a working project... spent a week trying to track down a weird bug only to discover that for some reason, D was trying to memset 1.5GB of memory at program startup, and then throwing Win32 exceptions every time I tried to use a string as part of an Exception! Tried to reduce it to a test case, but of course, I couldn't reproduce the problem... *grumble grumble* Sorry, just needed to vent a little. A week staring at assembler and WinDbg only to discover D is doing something strange will do that :P -- Daniel -- Unlike Knuth, I have neither proven or tried the above; it may not even make sense. v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Feb 25 2007
Saaa wroteWhen I uncomment the last line I get: Error: pictures: The system cannot find the file specified.
-manfred
Feb 25 2007
Sorry for wasting everybody's time.. Every time I wanted to see what went wrong I ran through commandline and as my pictures get read in relative.... ah well you'll get it :) At least Daniel found this thread useful ; )Not confirmed: DMD 1.007/WinXP32. -manfred
Feb 25 2007
How do I read the exceptions thrown in the main > scope(failure) ? Or should I just put everything in a try-catch ?
Feb 25 2007
Saaa wrote:How do I read the exceptions thrown in the main > scope(failure) ? Or should I just put everything in a try-catch ?
guards exist to ensure that any cleanup necessary (such as closing network connections or releasing mutexes in multithreaded programs) gets performed before all references to the associated resources are lost. To actually access the exceptions the exception needs to be thrown in the scope of a try block (somewhere, it doesn't need to be the immediate function) and that try block must have a catch and/or finally block.
Feb 25 2007
Okay, thanks.How do I read the exceptions thrown in the main > scope(failure) ? Or should I just put everything in a try-catch ?
scope guards exist to ensure that any cleanup necessary (such as closing network connections or releasing mutexes in multithreaded programs) gets performed before all references to the associated resources are lost. To actually access the exceptions the exception needs to be thrown in the scope of a try block (somewhere, it doesn't need to be the immediate function) and that try block must have a catch and/or finally block.
Feb 26 2007









"Saaa" <empty needmail.com> 