tags:

views:

141

answers:

6

Hello there,

I have a question regarding the following code snippet I came across in one of our older libraries.

try
{
  throw "this is an error message";
}
catch( char* error )
{
  cout << "an exception occured: " << error << endl;
}

My understanding of the behavior in this case is, that the error message is thrown by value, which means a copy of the text

"this is an error message"

is thrown. The catch clause specifies a pointer to char as expected type of exception. Can some enlighten me, why this works? Another question in this context concerns the memory allocated for the error message. Since the exception type is pointer to char* one could assume, that the memory for the error message has been allocated dynamically on the heap and has to be deleted by the user?

Thanks in advance

A: 

This works because the default type of "ANY STRING" is a pointer to a static char array.

Chris Kaminski
+2  A: 

Its not the string that is being thrown, but the pointer to the string. You do not have to delete it. The pointer points to a string literal, instantiated at the point of the call:

throw "this is an error message";

This string is not allocated on the stack, but statically. You could think of it as a compile time constant.

John Dibling
+5  A: 

It should actually catch const char* because that is the type of string constants both in C and C++.

It is passed by value, but by the value of the pointer.

It shouldn't be deleted, because as you can clearly see from the code, there is no dynamic allocation.

Let_Me_Be
Firstly, the type of string literal is an "array of char", not "pointer to char". A pointer is thrown in this case because of the standard array-to-pointer conversion (so called "array type decay"). Secondly, `const` is present in C++ only, but not in C. In C string literals have type `char[N]` and decay to `char *` pointers - no `const` there.
AndreyT
The difference can be seen better by considering that you can also throw functions: `void f() { try { throw f; } catch(void h()) { } }` Just like you can do `void g() { try { throw "foo"; } catch(char const i[4]) { } }` . What happens in behind the scenes is that actually a `void(*)()` and a `char const*` is thrown and caught, but not a function or an array. (quite similar to argument passing to a function, just that the deprecated string literal to `char*` conversion is not considered (because we are not converting from a string literal in the first place when we inspect the `catch`)).
Johannes Schaub - litb
A: 

I think you are almost right and the message is thrown by value. But not by char[XXX]. It's thrown by char*. And data is stored in static memory.

Alex
Like Let_Me_Be says, `char const*` is thrown. The catch should never be reached.
Johannes Schaub - litb
A: 

My understanding of the behavior in this case is, that the error message is thrown by value, which means a copy of the text [...] is thrown.

No, it means a copy of the pointer is thrown.

FredOverflow
+7  A: 

In throw context arrays decay to pointers. And string literal is an array of characters. This means that:

(1) What is "thrown by value" in this case is a const char * pointer to the existing string literal. No copy of string literal is made. No additional memory is allocated by this throw. There's no need to deallocate anything.

(2) In order to catch this exception you need a catch (const char *) handler. Your char * handler will not catch it, unless your compiler has a bug in it (this is a known persistent bug in MSVC++ compilers, which is not even fixed by /Za option).

AndreyT
thanks for the clearification on the MSVC++ compiler bug
Holger Kretzschmar