Question #1 :
The following code crashes in Visual C++ compiler. It fails in the expression _BLOCK_TYPE_IS_VALID(). It means that, it is deleting a bad pointer.
When I give a copy constructor, it works fine but the control does not even go in the copy constructor. Why is it showing this behaviour
Question #2 :
If I throw a local primitive type like an int, the address of that variable matches in the catch block if I am catching by reference. But for objects, the address for the variable in the catch block changes. Why
#include
<iostream>using
namespace std ;class
Exception{
char *m_pszError ;public
:Exception
(const char *p) {cout
<< "Exception::Exception()" << endl ;m_pszError
= new char[strlen(p) + 1] ;strcpy
(m_pszError, p) ; } ~Exception() {cout
<<"Exception::~Exception()"<< endl ; delete []m_pszError ; }}
;int
main(){
try { throw Exception("Test") ; } catch(Exception & ex) { } return 0 ;}

Exception handling showing undefined behaviour. Help !!!
Philippe Cand
Sparx
I tried lots of different ways to make it use the copy constructor but couldn't. The only thing that makes sense is that the stack unwinding code unwinds frames (adjusts the BP-register) but not the stack (the SP-register). That keeps the Exception object valid on the stack.
Another way to look at it is that they forgot to make the compiler smart when there is no copy constructor. I'm sure there's some good reason...
Onslaught_2000
John Mears
See sections 15.1/5 of the standard.
My guess is that in the presence of an accessible copy constructor and destructor, the compiler can eliminate the use of a temporary object. The copy is therefore actually never done, but it's existence indirectly cause the destructor to be called only once.
What I find odd is how the Exception class having an instance of another class (which has a ctor, copy ctor and dtor) seems to eliminate the temporary object (and thus destruction error) -- even without a copy ctor in the Exception class.
errolian
Now you have two instances, each has an m_pszError pointing to the heap block that contains "Test". The first one gets destructed just before the stack unwinds and deletes the heap block. The second one gets destructed after the catch handler executes and deletes the same heap block again. Boom.
When you provide the copy constructor, you won't create the duplicate pointers to the heap block. It also makes the compiler smart for some reason and it doesn't make the instance copy, that's why you don't get the break in the debugger. Note that the destructor only runs once, not twice.
I'm not sure why the address wouldn't change for a primitive type, other than the compiler being smart enough to re-use the stack frame address, but it changes when you throw the exception in another function. I'm not 100% sure if I got the details right but this has been my interpretation of what I've seen...
mshvw
Thanks for your kind reply.
But there is still some ambiguity about the way compiler manages it. You have written
It also makes the compiler smart for some reason and it doesn't make the instance copy, that's why you don't get the break in the debugger
What does this mean How does the compiler manage it What is making the compiler smart
Once again, thanks.
Alchemy_Mgt
What you're observing there is simply a quirk of the compiler - for whatever reason, it is able to elide the copy in some cases and not others. It's likely the result of a strategy that does a bitwise copy of POD classes to save some other processing.
In the case that crashes, the compiler is concluding the that class is POD since it has no copy constructor, while the presense of the copy constructor lets the compiler know that the class is not POD so it uses a different strategy - one that doesn't actually require copying the object but probably has some other cost(s) associated with it (otherwise why not just use that stragety in all cases ).
Scott Croisdale
Each time you allocate memory dynamically inside a class/struct, you have to provide a copy constructor and an assignment operator, because the ones the compiler automatically creates are doing a shallow copy, and you need a deep copy.
Moreover, why don't you simply use std::string instead of char* and avoid doing any memory allocation/releasing by yourself
ctrahan
Here's the trick: When you catch a C++ exception, the stack frame is set up as-if the catch block was called from the location of the throw.
That's how the original object address at the throw site can still exist at the catch site - that part of the stack is still active! IIRC, destructors on objects allocated in the "unwound" stack frames will have already run at the point of the catch, but the stack pointer itself isn't adjusted until after the catch block executes.
Of course, such details are completely implementation defined and could change at any time. I don't know if this situation is the same for x64, for example. I suspect that it's not, because the whole approach to exceptions in the x64 compiler is different (it uses a table-based approach rather than the frame-based approach that the x86 compiler uses).
The Standard requires that the class have an accessible copy-constructor. It doesn't require that the compiler uses it.
brother martin
alwz_nikhil