www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Exception Safe Programming

reply "Saaa" <empty needmail.com> writes:
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
next sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"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
parent reply "Saaa" <empty needmail.com> writes:
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
parent reply Tyler Knott <tywebmail mailcity.com> writes:
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
parent "Saaa" <empty needmail.com> writes:
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
prev sibling next sibling parent reply renoX <renosky free.fr> writes:
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
parent reply "Saaa" <empty needmail.com> writes:
"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
parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
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
parent reply "Saaa" <empty needmail.com> writes:
 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
parent Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
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
prev sibling next sibling parent reply "Saaa" <empty needmail.com> writes:
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
next sibling parent reply Tyler Knott <tywebmail mailcity.com> writes:
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
parent reply "Saaa" <empty needmail.com> writes:
 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
parent reply Tyler Knott <tywebmail mailcity.com> writes:
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
parent reply "Saaa" <empty needmail.com> writes:
 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
parent reply Tyler Knott <tywebmail mailcity.com> writes:
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
parent reply "Saaa" <empty needmail.com> writes:
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 :D

 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
parent Daniel Keep <daniel.keep.lists gmail.com> writes:
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 :D
 
 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);
 }

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
prev sibling parent reply Manfred Nowak <svv1999 hotmail.com> writes:
Saaa wrote
 When I uncomment the last line I get:
 Error: pictures: The system cannot find the file specified.

-manfred
Feb 25 2007
parent "Saaa" <empty needmail.com> writes:
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
prev sibling parent reply "Saaa" <empty needmail.com> writes:
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
parent reply Tyler Knott <tywebmail mailcity.com> writes:
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
parent "Saaa" <empty needmail.com> writes:
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