Topic: Queries about exceptions.


Author: "David Abrahams" <david.abrahams@rcn.com>
Date: Mon, 13 May 2002 17:33:36 GMT
Raw View
"Carl Daniel" <cpdaniel@pacbell.net> wrote in message
news:jriC8.158$If7.27242635@newssvr14.news.prodigy.com...
> "David Abrahams" <david.abrahams@rcn.com> wrote in message
> news:abc4q7$2ju$1@bob.news.rcn.net...
> >
> > "Carl Daniel" <cpdaniel@pacbell.net> wrote in message
> > news:5zSB8.1912$P27.233682019@newssvr14.news.prodigy.com...
> > > "Haneef Kazi" <haneefk@geometricsoftware.com> wrote in message
> > > news:aatan0$dm316$1@ID-56000.news.dfncis.de...
> > >
> > > The argument in a throw expression is (at least logically) copied
before
> > the
> > > exception propagates.  The compiler is free to optimize-away the copy
if
> > it
> > > can, but the program must always behave as-if the exception had been
> > copied.
> >
> > IIRC that's not quite right. The compiler may elide the copy, and the
> > elision is allowed to be observable. The constraint is upon the user:
the
> > thrown type is required to be copyable, even if the copy is elided.
> >
>
> Yeah, I know someone was going to call me on that  - that's what I get for
> going for a brief explanation!
>
> How 'bout if I say "other than the loss of one or more copy-constructor
> calls, the program must behave as-if the exception was copied" (insofar as
> the memory where the expection object was originally allocated may have
been
> "freed" (and hence have undefined content) but the exception object itself
> must always remain valid ("as-if" it had been copied, even if it hasn't).

See how complicated that's getting? It's getting that way because you're
trying to make the situation fit a model where the constraint is on the
implementation. The simple explanation is that the exception type is
required to be copyable, and the implementation is allowed to copy it. Why
not just say that?

-Dave



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Carl Daniel" <cpdaniel@pacbell.net>
Date: Fri, 10 May 2002 03:03:20 GMT
Raw View
"David Abrahams" <david.abrahams@rcn.com> wrote in message
news:abc4q7$2ju$1@bob.news.rcn.net...
>
> "Carl Daniel" <cpdaniel@pacbell.net> wrote in message
> news:5zSB8.1912$P27.233682019@newssvr14.news.prodigy.com...
> > "Haneef Kazi" <haneefk@geometricsoftware.com> wrote in message
> > news:aatan0$dm316$1@ID-56000.news.dfncis.de...
> >
> > The argument in a throw expression is (at least logically) copied before
> the
> > exception propagates.  The compiler is free to optimize-away the copy if
> it
> > can, but the program must always behave as-if the exception had been
> copied.
>
> IIRC that's not quite right. The compiler may elide the copy, and the
> elision is allowed to be observable. The constraint is upon the user: the
> thrown type is required to be copyable, even if the copy is elided.
>

Yeah, I know someone was going to call me on that  - that's what I get for
going for a brief explanation!

How 'bout if I say "other than the loss of one or more copy-constructor
calls, the program must behave as-if the exception was copied" (insofar as
the memory where the expection object was originally allocated may have been
"freed" (and hence have undefined content) but the exception object itself
must always remain valid ("as-if" it had been copied, even if it hasn't).

-cd


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Haneef Kazi" <haneefk@geometricsoftware.com>
Date: 5 May 2002 19:56:04 GMT
Raw View
Hi all,
   A few small queries regarding exceptions...

   If I throw a local char array on stack from inside a function, does
   it always remain valid in the catch block of its caller? I tested
   it with the immediate caller and found that it does remain valid.
   1. I am curious whether it will remain valid for a caller with multiple
   levels of call stack. e.g. A calls B, which calls C, which calls D.
   Now if D throws a char array, which is not caught by either C or B, but
   is caught by A, then will it be legal to access the thrown char array
   from inside the catch block for char* inside A??
   2. I have tested the one level condition on VC 6.0; does standard C++
   allow to access the local variable of callee inside catch block of the
   caller, and is it supported on other compilers?

   Finally here is an interesting code - I have assigned two different
   literal values to a local char array in each of the functions foo and
   bar. foo throws the local char array, and bar only assigns the value.
   Now, if I call foo inside a try block and inside the catch block for
   char* I call bar(marked "Call number 1"), I find that the local string
   in bar does not override the memory of local string in foo.
   On the other hand if I call bar after the completion of catch block
   (marked "Call number 2"), its local array overrides the memory! I
   checked this in VC++'s debugger.
   This shows that the stack variables are safe in the catch block and
   become illegal as soon as the catch block completes execution.
   Please let me know whether what I infer here is correct. Also is it
   standard and supported on other compilers or not.

   PS: Kindly ignore use of printf and non standard C++ usages and focus
   on the actual questions asked - this is only a simple code for testing
   the required conditions and not a full flowing C++ code for delivery. :-)

Cheers,

Haneef.


=====================================================


#include <stdio.h>
#include <process.h>
#include <exception>
#include <string.h>

void foo()
{
   char szfoo[50];
   strcpy(szfoo, "Throwing exception");
   throw szfoo;
}

void bar()
{
   char szbar[100];
   strcpy(szbar, "This is a long string to override previous string");
}

int main(void)
{
   try
   {
      foo();
   }
   catch(char* p)
   {
      bar();         // Call number 1.
      printf(p);
   }

   bar();            // Call number 2.

   return 0;
}






      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]






Author: "Carl Daniel" <cpdaniel@pacbell.net>
Date: Wed, 8 May 2002 02:24:16 GMT
Raw View
"Haneef Kazi" <haneefk@geometricsoftware.com> wrote in message
news:aatan0$dm316$1@ID-56000.news.dfncis.de...
>
> Hi all,
>    A few small queries regarding exceptions...
>
>    If I throw a local char array on stack from inside a function, does
>    it always remain valid in the catch block of its caller? I tested
>    it with the immediate caller and found that it does remain valid.
>    1. I am curious whether it will remain valid for a caller with multiple
>    levels of call stack. e.g. A calls B, which calls C, which calls D.
>    Now if D throws a char array, which is not caught by either C or B, but
>    is caught by A, then will it be legal to access the thrown char array
>    from inside the catch block for char* inside A??

Yes (see below).

>    2. I have tested the one level condition on VC 6.0; does standard C++
>    allow to access the local variable of callee inside catch block of the
>    caller, and is it supported on other compilers?

No.  The local variables of the aborted context (the one that threw the
exception), and all intermediate contexts between the point of the throw and
the catch are logically destroyed before the catch is entered. (See below).

>
>    Finally here is an interesting code - I have assigned two different
>    literal values to a local char array in each of the functions foo and
>    bar. foo throws the local char array, and bar only assigns the value.
>    Now, if I call foo inside a try block and inside the catch block for
>    char* I call bar(marked "Call number 1"), I find that the local string
>    in bar does not override the memory of local string in foo.
>    On the other hand if I call bar after the completion of catch block
>    (marked "Call number 2"), its local array overrides the memory! I
>    checked this in VC++'s debugger.
>    This shows that the stack variables are safe in the catch block and
>    become illegal as soon as the catch block completes execution.
>    Please let me know whether what I infer here is correct. Also is it
>    standard and supported on other compilers or not.

The argument in a throw expression is (at least logically) copied before the
exception propagates.  The compiler is free to optimize-away the copy if it
can, but the program must always behave as-if the exception had been copied.

The particular behavior that you're seeing with regard to the contexts in
which a local variable in a function called from within a catch block
overwrites the memory which originally held the exception is an artifact of
the way VC implements exception handling and cannot be relied upon in
general.

Under the VC implementation, in fact, the catch clause which handles an
exception is effectively called as a subroutine from the point of the
original exception throw - the stack frames "below" that "catch function"
have been unwound (local object destructors called), but the memory hasn't
been deallocated.  This technique allows VC to avoid copying the exception
object in many cases, since it's already on the stack where it needs to be.

Other compilers use other techniques.  In the case of your example, when you
enter the catch(char *), all local variables of foo have been logically
destroyed.  The fact that the memory hasn't been overwritten by something
else is simply a side-effect that you cannot count on.  If foo had a local
variable of class type with a destructor, the destructor is guaranteed to
have run before the catch clause is entered.

Also, please don't cross-post to multiple moderated groups.

HTH

-cd




---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "David Abrahams" <david.abrahams@rcn.com>
Date: Wed, 8 May 2002 21:35:58 GMT
Raw View
"Carl Daniel" <cpdaniel@pacbell.net> wrote in message
news:5zSB8.1912$P27.233682019@newssvr14.news.prodigy.com...
> "Haneef Kazi" <haneefk@geometricsoftware.com> wrote in message
> news:aatan0$dm316$1@ID-56000.news.dfncis.de...
>
> The argument in a throw expression is (at least logically) copied before
the
> exception propagates.  The compiler is free to optimize-away the copy if
it
> can, but the program must always behave as-if the exception had been
copied.

IIRC that's not quite right. The compiler may elide the copy, and the
elision is allowed to be observable. The constraint is upon the user: the
thrown type is required to be copyable, even if the copy is elided.

sticking-my-neck-out-without-reading-the-standard-ly y'rs,
dave



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Roger Orr" <rogero@howzatt.demon.co.uk>
Date: Wed, 8 May 2002 22:54:28 GMT
Raw View
David Abrahams wrote in message ...
>
>"Carl Daniel" <cpdaniel@pacbell.net> wrote in message
>news:5zSB8.1912$P27.233682019@newssvr14.news.prodigy.com...
>> "Haneef Kazi" <haneefk@geometricsoftware.com> wrote in message
>> news:aatan0$dm316$1@ID-56000.news.dfncis.de...
>>
>> The argument in a throw expression is (at least logically) copied before
>the
>> exception propagates.  The compiler is free to optimize-away the copy if
>it
>> can, but the program must always behave as-if the exception had been
>copied.
>
>IIRC that's not quite right. The compiler may elide the copy, and the
>elision is allowed to be observable. The constraint is upon the user: the
>thrown type is required to be copyable, even if the copy is elided.
>
>sticking-my-neck-out-without-reading-the-standard-ly y'rs,
>dave


Your neck is safe :-) see 15.1p5.

--
Roger Orr
MVP in C++ at www.brainbench.com


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]