"try{throw}catch"

D

dick

in the "try{throw}catch" structure, how the C++ code return the "type"
thrown by a function?
 
A

Alf P. Steinbach

* dick:
in the "try{throw}catch" structure, how the C++ code return the "type"
thrown by a function?

Short answer: Magic.

Almost-short answer: the dynamic type of the object throw by 'throw' is
known statically, and is the same as the static type because objects are
thrown by value, and the static type of object caught by 'catch' is
known statically, and is the only thing that matters for whether a
'catch' clause will catch. The linker has access to all this
information. And so it can arrange the necessary tables or global type
identifiers or whatever the implementation is based on (there are two
main ways to do it, but an infinite number of possible ways to do it).
 
S

Salt_Peter

dick said:
in the "try{throw}catch" structure, how the C++ code return the "type"
thrown by a function?

That depends on the function's exception specification.
The function is not "returning" the error, the execution context is
throwing the anomally. Where, if and when the anomally is caught
depends on guarded contexts (try blocks) and their catch blocks.

Thats like asking how does an integer know that its an integer? You
can't do anything in C++ without the type being known. Objects always
know their type or type(s) if inheritance is involved. If you throw a
baseball, the baseball knows its a baseball. If you construct and throw
a std::runtime_error, trust me, the object knows that its a
runtime_error. even if you catch( const std::exception& e) - a
reference to its base, the runtime_error still knows its a
runtime_error.
 
D

dick

Salt_Peter said:
That depends on the function's exception specification.
The function is not "returning" the error, the execution context is
throwing the anomally. Where, if and when the anomally is caught
depends on guarded contexts (try blocks) and their catch blocks.

Thats like asking how does an integer know that its an integer? You
can't do anything in C++ without the type being known. Objects always
know their type or type(s) if inheritance is involved. If you throw a
baseball, the baseball knows its a baseball. If you construct and throw
a std::runtime_error, trust me, the object knows that its a
runtime_error. even if you catch( const std::exception& e) - a
reference to its base, the runtime_error still knows its a
runtime_error.





But how the "catch" know the type.
 
D

dick

Alf said:
* dick:

Short answer: Magic.

Almost-short answer: the dynamic type of the object throw by 'throw' is
known statically, and is the same as the static type because objects are
thrown by value, and the static type of object caught by 'catch' is
known statically, and is the only thing that matters for whether a
'catch' clause will catch. The linker has access to all this
information. And so it can arrange the necessary tables or global type
identifiers or whatever the implementation is based on (there are two
main ways to do it, but an infinite number of possible ways to do it).

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

is there any memory leak when a function throw an object?
 
S

Salt_Peter

dick said:
But how the "catch" know the type.

The catch does not need to know the type. In fact, if the catch is
catch(...) { }
It will never know the type.
Since catch blocks typically have a specific parameter, anything that
is succesfully "caught" by the parameter is therefore of that type or
derived of that type.

Its really a simple system.

int main()
{
try {
throw std::string("error");
{
catch( integer& e ) // can only catch integers
{
}
catch ( std::string& e) // can only catch std::string or derivatives
{
std::cerr << e << std::endl
}
catch( ... )
{
}
}

Its obvious that the thrown object can only initialize the second catch
block's parameter.
Hence, the std::string's type is known.
 
S

Salt_Peter

dick said:
is there any memory leak when a function throw an object?

Oh yes there can be. *If* you allocate with new, the compiler is no
longer responsible for that allocation. That does not change when an
exception is thrown.
Obviously, any local objects are automatically destroyed. The same
holds with smart pointers.

You can safely protect yourself:
a) by not using new/delete
b) using smart pointers
c) by having the catch block check for and deallocate any newed
allocations. That - you need to do carefully.

Take for example the code below and lets artificially throw a
bad_allocation exception before delete invokes A's d~tor.

#include <iostream>
#include <stdexcept>

class A
{
};

int main()
{
// pointer must not be in try block
A* p_a = 0; // nullified
try
{
A a; // local
p_a = new A;
std::cout << "p_a = " << p_a << std::endl;
// do stuff and throw for a test
throw std::bad_alloc(); // or std::runtime_error
delete p_a;
std::cout << "end of try block\n";
}
catch( const std::exception& e)
{
std::cerr << "error: ";
std::cerr << e.what() << std::endl;
std::cerr << "p_a = " << p_a << std::endl;
if(p_a)
{
delete p_a;
std::cerr << "*** p_a deleted ***" << std::endl;
}
}
}

/*
p_a = 0x503010
<- "end of try block" was never reached
error: St::bad_alloc <- in catch block
p_a = 0x503010
*** p_a deleted ***
*/
 
N

Noah Roberts

dick said:
is there any memory leak when a function throw an object?

You have questions about exception safety. Instead of asking them all
you might think about buying the book "Exceptional C++", which should
answer many and even ones you never thought to ask.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,038
Latest member
OrderProperKetocapsules

Latest Threads

Top