C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

it's so simple, why is it wrong?
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
jkhongyu@yahoo.com
Guest





PostPosted: Wed Dec 10, 2003 11:36 am    Post subject: it's so simple, why is it wrong? Reply with 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 <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





PostPosted: Wed Dec 10, 2003 4:05 pm    Post subject: Re: it's so simple, why is it wrong? Reply with quote



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





PostPosted: Wed Dec 10, 2003 4:26 pm    Post subject: Re: it's so simple, why is it wrong? Reply with quote



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





PostPosted: Wed Dec 10, 2003 8:15 pm    Post subject: Re: it's so simple, why is it wrong? Reply with 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.

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





PostPosted: Wed Dec 10, 2003 8:16 pm    Post subject: Re: it's so simple, why is it wrong? Reply with quote

[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





PostPosted: Wed Dec 10, 2003 8:17 pm    Post subject: Re: it's so simple, why is it wrong? Reply with quote

[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





PostPosted: Wed Dec 10, 2003 8:18 pm    Post subject: Re: it's so simple, why is it wrong? Reply with quote

[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





PostPosted: Wed Dec 10, 2003 8:21 pm    Post subject: Re: it's so simple, why is it wrong? Reply with quote

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





PostPosted: Wed Dec 10, 2003 8:22 pm    Post subject: Re: it's so simple, why is it wrong? Reply with quote

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





PostPosted: Wed Dec 10, 2003 8:31 pm    Post subject: Re: it's so simple, why is it wrong? Reply with quote

[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





PostPosted: Wed Dec 10, 2003 8:36 pm    Post subject: Re: it's so simple, why is it wrong? Reply with quote

[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





PostPosted: Thu Dec 11, 2003 10:40 am    Post subject: Re: it's so simple, why is it wrong? Reply with quote

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





PostPosted: Thu Dec 11, 2003 10:40 am    Post subject: Re: it's so simple, why is it wrong? Reply with quote

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





PostPosted: Thu Dec 11, 2003 11:38 am    Post subject: Re: it's so simple, why is it wrong? Reply with quote

[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





PostPosted: Thu Dec 11, 2003 11:41 am    Post subject: Re: it's so simple, why is it wrong? Reply with quote


"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
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.