 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
jkhongyu@yahoo.com Guest
|
Posted: Wed Dec 10, 2003 11:36 am Post subject: it's so simple, why is it wrong? |
|
|
Dear all,
I haven't really written any C++ code in recent two years, so lots of
my old kknowledge and concept just don't work for me anymore. Still
it's hard for me to understand why the following code is not working
anymore.
#include <iostream>
int main () {
try
{
throw "out of range";
}
catch (char * str)
{
cout << "Exception: " << str << endl;
}
return 0;
}
I can compile it under several versions of Linux ( from gcc 2.96 of
RedHat 7.3 to gcc 3.3.1 of latest Mandrake) without any error, but the
executable code aborted when I run it, displaying: Abort (core
dumped).
I saw similar examples from text books somewhere. Also, if I change
the constant string "Out of range" to a string variable, this code
works. So is it a string related problem?
Thanks!
JK
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Alf P. Steinbach Guest
|
Posted: Wed Dec 10, 2003 4:05 pm Post subject: Re: it's so simple, why is it wrong? |
|
|
On 10 Dec 2003 06:36:03 -0500, [email]jkhongyu (AT) yahoo (DOT) com[/email] (jkhongyu (AT) yahoo (DOT) com) wrote:
| Quote: | I haven't really written any C++ code in recent two years, so lots of
my old kknowledge and concept just don't work for me anymore. Still
it's hard for me to understand why the following code is not working
anymore.
#include
int main () {
try
{
throw "out of range";
}
catch (char * str)
{
cout << "Exception: " << str << endl;
}
return 0;
}
|
If this "worked" then your exception handler could modify the
string constant.
Instead, try
catch( char const* str )
But as a matter of coding style, _do not_ throw anything else than
objects of std::exception or derived classes.
Personal preference: throw std::rutime_error or derived for situations
where 'assert' would be completely inappropriate, throw an object of
class std::exception or a derived class that is not in the std::runtime_error
tree for exceptions where 'assert' could conceivably be used.
The rationale for that preference is that std::bad_exception does not derive
from std::logic_error (and std::bad_alloc is a mysterious beast), and that it
allows code to catch only std::runtime_error (and derived), thus passing the
more hopeless, fun-spoiling exceptions up to a top-level handler.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Wed Dec 10, 2003 4:26 pm Post subject: Re: it's so simple, why is it wrong? |
|
|
In article <2c7916f0.0312092255.3da0c7e5 (AT) posting (DOT) google.com>,
"jkhongyu (AT) yahoo (DOT) com" <jkhongyu (AT) yahoo (DOT) com> writes
| Quote: | Dear all,
I haven't really written any C++ code in recent two years, so lots of
my old kknowledge and concept just don't work for me anymore. Still
it's hard for me to understand why the following code is not working
anymore.
#include
int main () {
try
{
throw "out of range";
}
catch (char * str)
{
cout << "Exception: " << str << endl;
}
return 0;
}
I can compile it under several versions of Linux ( from gcc 2.96 of
RedHat 7.3 to gcc 3.3.1 of latest Mandrake) without any error, but the
executable code aborted when I run it, displaying: Abort (core
dumped).
I saw similar examples from text books somewhere. Also, if I change
the constant string "Out of range" to a string variable, this code
works. So is it a string related problem?
|
The critical change is that the type of a string literal is now an array
of n const char which decays to char const *. In a restricted number of
contexts (to preserve legacy code) there is a conversion from string
literal to char*. The above is not one of those cases. What you have
thrown is an const char[14] which can be caught as either a const
char[14] & (possibly const qualified) or as a char const *.
Of course there is nothing wrong with any individual line of your source
code and so it will always compile but the catch will fail to catch the
exception thrown hence your program terminates with an 'unhandled
exception error.'
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Travis Spencer Guest
|
Posted: Wed Dec 10, 2003 8:15 pm Post subject: Re: it's so simple, why is it wrong? |
|
|
Hey JK,
There are a couple things you can do:
1. Insert the line 'using namespace std' directly below the #include.
2. Include iostream.h instead of the current one you are using; this will
avoid the need for a using declaration.
3. In main, insert the lines 'using std::cout' and 'using std::end'
To find out why these solutions fix the problem, check out the explination
of namespaces in you C++ book or post back here w/ more questions.
Have a nice day.
--
Regards,
Travis Spencer
<jkhongyu (AT) yahoo (DOT) com> wrote
| Quote: | Dear all,
I haven't really written any C++ code in recent two years, so lots of
my old kknowledge and concept just don't work for me anymore. Still
it's hard for me to understand why the following code is not working
anymore.
#include
int main () {
try
{
throw "out of range";
}
catch (char * str)
{
cout << "Exception: " << str << endl;
}
return 0;
}
I can compile it under several versions of Linux ( from gcc 2.96 of
RedHat 7.3 to gcc 3.3.1 of latest Mandrake) without any error, but the
executable code aborted when I run it, displaying: Abort (core
dumped).
I saw similar examples from text books somewhere. Also, if I change
the constant string "Out of range" to a string variable, this code
works. So is it a string related problem?
Thanks!
JK
|
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Tom Guest
|
Posted: Wed Dec 10, 2003 8:16 pm Post subject: Re: it's so simple, why is it wrong? |
|
|
[email]jkhongyu (AT) yahoo (DOT) com[/email] wrote:
| Quote: | #include
int main () {
try
{
throw "out of range";
}
catch (char * str)
|
catch (const char* str)
or
catch (const char str[])
| Quote: | {
cout << "Exception: " << str << endl;
|
std::cout << "Exception: " << str << std::endl;
| Quote: | }
return 0;
}
I can compile it under several versions of Linux ( from gcc 2.96 of
RedHat 7.3 to gcc 3.3.1 of latest Mandrake) without any error,
|
I'm surprised to hear that - you didn't qualify cout or endl with std::.
| Quote: | but the
executable code aborted when I run it, displaying: Abort (core
dumped).
|
String literals are arrays of const chars, not arrays of chars.
Best regards,
Tom
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Frank Thilo Guest
|
Posted: Wed Dec 10, 2003 8:17 pm Post subject: Re: it's so simple, why is it wrong? |
|
|
[email]jkhongyu (AT) yahoo (DOT) com[/email] <jkhongyu (AT) yahoo (DOT) com> wrote:
: #include <iostream>
: int main () {
: try
: {
: throw "out of range";
: }
: catch (char * str)
: {
: cout << "Exception: " << str << endl;
std::cout << "Exception: " << str << std::endl;
: }
: return 0;
: }
: I saw similar examples from text books somewhere. Also, if I change
: the constant string "Out of range" to a string variable, this code
: works. So is it a string related problem?
"out of range" is of type const char[13] and gets thrown as a const char*
pointing to the first character. You try to catch a pointer to a non-const
char, which does not match your exception.
catch (const char *str)
should work fine. When you use an extra variable like:
try
{
char * exc = "out of range";
throw exc;
}
a special rule kicks in which allows string literals to be assigned to
char * for backward compatibility (discussed in another thread recently).
When you then throw this variable, it is of type char * without the const
and can be caught by your catch phrase.
--
Frank Thilo - [email]thilo (AT) unix-ag (DOT) org[/email] IRC: Chestal
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ulrich Eckhardt Guest
|
Posted: Wed Dec 10, 2003 8:18 pm Post subject: Re: it's so simple, why is it wrong? |
|
|
[email]jkhongyu (AT) yahoo (DOT) com[/email] wrote:
| Quote: | try
{
throw "out of range";
}
catch (char * str)
{
cout << "Exception: " << str << endl;
}
|
Try this more condensed version:
char* str = "out of range";
String literals are constants in C++.
Uli
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Andreas Scherer Guest
|
Posted: Wed Dec 10, 2003 8:21 pm Post subject: Re: it's so simple, why is it wrong? |
|
|
| Quote: | try
{
throw "out of range";
}
catch (char * str)
{
cout << "Exception: " << str << endl;
}
|
Try catching a "const char* str"; this works with g++ 2.95.3 and 3.3.1.
Or, preferably, use something like
#include
[...]
try
{
throw std::out_of_range( "Your message here" );
}
catch ( const std::exception& e )
{
std::cout << "Exception: " << e.what() << std::endl;
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Thomas Richter Guest
|
Posted: Wed Dec 10, 2003 8:22 pm Post subject: Re: it's so simple, why is it wrong? |
|
|
Hi,
| Quote: | int main () {
try
{
throw "out of range";
}
catch (char * str)
{
cout << "Exception: " << str << endl;
}
return 0;
}
|
| Quote: | I can compile it under several versions of Linux ( from gcc 2.96 of
RedHat 7.3 to gcc 3.3.1 of latest Mandrake) without any error, but the
executable code aborted when I run it, displaying: Abort (core
dumped).
|
This is because "out of range" is a "const char *", not a "char *". Change
that and it'll work fine.
Greetings,
Thomas
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Richard Smith Guest
|
Posted: Wed Dec 10, 2003 8:31 pm Post subject: Re: it's so simple, why is it wrong? |
|
|
[email]jkhongyu (AT) yahoo (DOT) com[/email] (jkhongyu (AT) yahoo (DOT) com) wrote:
| Quote: | try
{
throw "out of range";
|
A string literal is of type const char*.
| Quote: | }
catch (char * str)
|
This has different constness, so won't catch your string. Change this
to
catch ( const char* str )
and it should work.
| Quote: | I can compile it under several versions of Linux ( from gcc 2.96 of
RedHat 7.3 to gcc 3.3.1 of latest Mandrake) without any error, but the
executable code aborted when I run it, displaying: Abort (core
dumped).
|
As you would expect -- the exception is never caught, std::terminate
is called which calls abort(). On POSIX-compliant systems, e.g.
Linux, this will raise SIGABRT, resulting in the behaviour you
describe.
In general, it is bad practice to throw string literals about. A much
better idea is to throw some sort of exception class. The Standard
library provides just such a class: std::exception. I suggest you use
this instead.
--
Richard Smith
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ben Hutchings Guest
|
Posted: Wed Dec 10, 2003 8:36 pm Post subject: Re: it's so simple, why is it wrong? |
|
|
[email]jkhongyu (AT) yahoo (DOT) com[/email] wrote:
| Quote: | Dear all,
I haven't really written any C++ code in recent two years, so lots of
my old kknowledge and concept just don't work for me anymore. Still
it's hard for me to understand why the following code is not working
anymore.
|
Evidently you upgraded to a more standard-compliant compiler.
However, the first standard was completed over 5 years ago so the
changes aren't all that new.
| Quote: | #include
int main () {
try
{
throw "out of range";
|
In standard C++, string literals have type const char[N] where N is
the length of the string including the null terminator. When thrown,
this undergoes the standard array-to-pointer conversion resulting in
an exception of type const char *. This is of course not convertible
to type char * without a cast.
| Quote: | }
catch (char * str)
{
cout << "Exception: " << str << endl;
}
return 0;
}
I can compile it under several versions of Linux ( from gcc 2.96 of
RedHat 7.3 to gcc 3.3.1 of latest Mandrake) without any error, but the
executable code aborted when I run it, displaying: Abort (core
dumped).
I saw similar examples from text books somewhere. Also, if I change
the constant string "Out of range" to a string variable, this code
works. So is it a string related problem?
|
In earlier versions of C++ and in C, string literals have type
char *. For compatibility, standard C++ provides a standard
conversion of string literals to type char *, but this is not used
when an exception is thrown.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Thu Dec 11, 2003 10:40 am Post subject: Re: it's so simple, why is it wrong? |
|
|
In article <br7ekh02d2g (AT) enews3 (DOT) newsguy.com>, Travis Spencer
<travislspencer (AT) hotmail (DOT) com> writes
| Quote: | Hey JK,
There are a couple things you can do:
1. Insert the line 'using namespace std' directly below the #include.
2. Include iostream.h instead of the current one you are using; this will
avoid the need for a using declaration.
3. In main, insert the lines 'using std::cout' and 'using std::end'
To find out why these solutions fix the problem, check out the explination
of namespaces in you C++ book or post back here w/ more questions.
|
They don't, however they may hide it.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Daniel Krügler (nee Spang Guest
|
Posted: Thu Dec 11, 2003 10:40 am Post subject: Re: it's so simple, why is it wrong? |
|
|
Hello, Ulrich!
Ulrich Eckhardt schrieb:
| Quote: | jkhongyu (AT) yahoo (DOT) com wrote:
try
{
throw "out of range";
}
catch (char * str)
{
cout << "Exception: " << str << endl;
}
Try this more condensed version:
char* str = "out of range";
String literals are constants in C++.
|
Regrettably your expression does compile successfully
on conforming compilers due to backward-compatibility
to C.
Or did you mean the following:
char* str = "out of range";
throw str;
?? - which is OK, of course!
Daniel
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Dietmar Kuehl Guest
|
Posted: Thu Dec 11, 2003 11:38 am Post subject: Re: it's so simple, why is it wrong? |
|
|
[email]jkhongyu (AT) yahoo (DOT) com[/email] (jkhongyu (AT) yahoo (DOT) com) wrote:
| Quote: | try
{
throw "out of range";
|
Here you throw an object of type 'char const*'
| Quote: | }
catch (char * str)
{
cout << "Exception: " << str << endl;
}
|
.... but there is no handler for it! You might want to try
catch (char const* str)
{
std::cout << "Exception: " << str << std::endl;
}
instead. Of course, I would recommend to use the standard exception classes:
try { throw std::out_of_range("out of range..."); }
catch (std::exception const& ex)
{
std::cout << "Exception: " << ex.what() << "n";
}
At the very least, you should probably derive the classes you are intending
to throw from 'std::exception'.
--
Phaidros eaSE - Easy Software Engineering: <http://www.phaidros.com/>
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ron Natalie Guest
|
Posted: Thu Dec 11, 2003 11:41 am Post subject: Re: it's so simple, why is it wrong? |
|
|
"Francis Glassborow" <francis (AT) robinton (DOT) demon.co.uk> wrote
| Quote: | The critical change is that the type of a string literal is now an array
of n const char which decays to char const *. In a restricted number of
contexts (to preserve legacy code) there is a conversion from string
literal to char*. The above is not one of those cases. What you have
thrown is an const char[14] which can be caught as either a const
char[14] & (possibly const qualified) or as a char const *.
|
The problem is that it has no clue that you are converting const char[...] to
char* so it can't cheat on the conversion. The throw converts the value to
const char* when it makes the copy implicit in the throw. That as you say
doesn't match the char*.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|