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 

Foward decleration casting craziness

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
speedplane
Guest





PostPosted: Sun Jul 16, 2006 5:41 pm    Post subject: Foward decleration casting craziness Reply with quote



Hi there...
I just found a bug in a very well known compiler and I was wondering if
others have found the same problem. Consider the code snippet

class C; // Foward decleration
class A {
public:
// Here we cast to C but we don't know how to cast an A to
C* getAasC{ return (C*)this; };C
int a;
};
Note that this code will compile (in my compiler at least) even though
it does not know how to cast an A to a C. In another file say we define
C:
class B {
public:
int b;
};

class C : public B, A {
public;
int c;
}

In the first code snippet, the compiler does not know how to cast an A
to a C. Therefore it does a reinterpret cast instead of a static cast.
Consider the following code:
A * a = new C();
a->a = 50;
printf("A: %d, C: %d", a->a, a->getAasC()->c)
Depending on how you compiler does the reintpret cast the above will
either segfault or print:
A: 50, C: 50
My compiler didn't even give me a warning! I think it should give you
an error if you try to cast something and it doesn't know how to do the
cast.
Has anyone else run into something like this?


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Earl Purple
Guest





PostPosted: Sun Jul 16, 2006 11:05 pm    Post subject: Re: Foward decleration casting craziness Reply with quote



speedplane wrote:
Quote:
Hi there...
I just found a bug in a very well known compiler and I was wondering if
others have found the same problem. Consider the code snippet

class C; // Foward decleration
class A {
public:
// Here we cast to C but we don't know how to cast an A to
C* getAasC{ return (C*)this; };C
int a;
};
Note that this code will compile (in my compiler at least) even though
it does not know how to cast an A to a C. In another file say we define

As long as the C at the end of the line that begins C* is a typo and
not there in the code, there is no reason why it shouldn't compile.

C-style casting basically tells the compiler to shut up and compile,
and it does just that. Of course, it could be that C is privately
derived from A and is some form of implementation class for it (and
will always be the implementation for it in a weird sort of pImpl
pattern), in which case your cast may well be valid. From the code that
followed it appeared to be the case.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Jiang
Guest





PostPosted: Sun Jul 16, 2006 11:06 pm    Post subject: Re: Foward decleration casting craziness Reply with quote



speedplane wrote:
Quote:
Hi there...
I just found a bug in a very well known compiler and I was wondering if
others have found the same problem. Consider the code snippet

class C; // Foward decleration
class A {
public:
// Here we cast to C but we don't know how to cast an A to
C* getAasC{ return (C*)this; };C
int a;
};
Note that this code will compile (in my compiler at least) even though
it does not know how to cast an A to a C. In another file say we define
C:
class B {
public:
int b;
};

class C : public B, A {
public;
int c;
}

In the first code snippet, the compiler does not know how to cast an A
to a C. Therefore it does a reinterpret cast instead of a static cast.
Consider the following code:
A * a = new C();
a->a = 50;
printf("A: %d, C: %d", a->a, a->getAasC()->c)
Depending on how you compiler does the reintpret cast the above will
either segfault or print:
A: 50, C: 50


Nothing strange in my mind, the standard says that:

[quote]

5.2.10:

3 The mapping performed by reinterpret_cast is implementation-defined.
[Note: it might, or might not, produce a representation different
from the original value. ]

4 A pointer can be explicitly converted to any integral type large
enough to hold it. The mapping function is implementation-defined
[Note: it is intended to be unsurprising to those who know the
addressing structure of the underlying machine. ]

[end quote]


Quote:
My compiler didn't even give me a warning! I think it should give you
an error if you try to cast something and it doesn't know how to do the
cast.


But the above conversion is well-defined according to the standard,
and the compilers do know how to do the cast.

In the same section of the standard, we have:

[quote]

7 A pointer to an object can be explicitly converted to a pointer to
an object of different type. Except that converting an rvalue
of type "pointer to T1" to the type "pointer to T2" (where T1 and T2
are object types and where the alignment requirements of T2 are no
stricter than those of T1) and back to its original type yields the
original pointer value, the result of such a pointer conversion is
unspecified.

[end quote]

So you see the conversion itself is valid, but the result depends on
the definitions of A and C. That is, who wrote such conversion will be
responsible for the surprising or unsurprising result. :-)


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Pete Becker
Guest





PostPosted: Sun Jul 16, 2006 11:07 pm    Post subject: Re: Foward decleration casting craziness Reply with quote

speedplane wrote:
Quote:
Hi there...
I just found a bug in a very well known compiler and I was wondering if
others have found the same problem. Consider the code snippet

class C; // Foward decleration
class A {
public:
// Here we cast to C but we don't know how to cast an A to
C* getAasC{ return (C*)this; };C
int a;
};
Note that this code will compile (in my compiler at least) even though
it does not know how to cast an A to a C.

It's not about converting an A to a C, but about converting pointers. A
C-style cast tells the compiler that you know what you're doing, and it
should just shut up and do the conversion. Which is what it did. Since
there is no information about the relationship between A and C, it
treats the value of the pointer as a pointer to C.

In another file say we define
Quote:
C:
class B {
public:
int b;
};

class C : public B, A {
public;
int c;
}

In the first code snippet, the compiler does not know how to cast an A
to a C. Therefore it does a reinterpret cast instead of a static cast.

No, it did a C-style pointer conversion, because that's what the code
tells it to do. If the code had uses static_cast for the pointer
conversion the compiler would have issued a diagnostic.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Guest






PostPosted: Sun Jul 16, 2006 11:07 pm    Post subject: Re: Foward decleration casting craziness Reply with quote

speedplane wrote:
Quote:
Hi there...
I just found a bug in a very well known compiler and I was wondering if
others have found the same problem. Consider the code snippet

class C; // Foward decleration
class A {
public:
// Here we cast to C but we don't know how to cast an A to
C* getAasC{ return (C*)this; };C
int a;
};

Why do you think that compiler doesn't know how to cast an A* to C*?
These are just two raw pointers and static casting involved only. After
program link, your main function will know class C's definition and
execute the right function.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
LR
Guest





PostPosted: Sun Jul 16, 2006 11:09 pm    Post subject: Re: Foward decleration casting craziness Reply with quote

speedplane wrote:

Quote:
class C; // Foward decleration

I don't think this has anything to do with forward declarations.

Quote:
class A {
public:
// Here we cast to C but we don't know how to cast an A to

You are casting an A* to a C*. Not the same as casting A to C.
It's probably not a good idea, but I'm not certain that it's an actual
compiler bug.

Quote:
C* getAasC{ return (C*)this; };C
^^

I'm not quite sure what that is.


Quote:
int a;
};

FWIW, Comeau's try it out compiles this without complaint, but Gimpel's
Blank Slate gives an informative message (not a warning) about this.

LR

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
James Kanze
Guest





PostPosted: Tue Jul 18, 2006 1:44 am    Post subject: Re: Foward decleration casting craziness Reply with quote

speedplane wrote:

Quote:
I just found a bug in a very well known compiler and I was
wondering if others have found the same problem. Consider the
code snippet

class C; // Foward decleration
class A {
public:
// Here we cast to C but we don't know how to cast an A to
C* getAasC{ return (C*)this; };C
int a;
};

Note that this code will compile (in my compiler at least)
even though it does not know how to cast an A to a C.

Historical reasons. The compiler thinks it knows, even though
it doesn't.

This is a very good example of why the new casts were added to
the language. You're code uses a C-style cast, which can mean
many different things. Unless the compiler has actually seen
the definition of C, and knows that it should interpret the C
style cast as a static_cast, it supposes that a reinterpret_cast
is meant.

In all cases where the target of a cast is a pointer or a
reference, only a new style cast should be used, to tell the
compiler what type of cast you want. Then, if the compiler
doesn't have the information to do the type of cast you want, or
the cast isn't legal, it will output an error message, rather
than doing something else that you didn't want. (I sort of
favor new style casts in most cases, but when pointers or
references are involved, it's no longer a question of style or
personal preferences---only new style casts are acceptable.
Precisely because the C style cast is ambiguous.)

Quote:
In another file say we define
C:
class B {
public:
int b;
};

class C : public B, A {
public;
int c;
}

In the first code snippet, the compiler does not know how to
cast an A to a C.

No. In the first code snippet, you told the compiler to cast an
A to a C however it felt like. The compiler didn't know how to
do a static_cast, so it did a reinterpret_cast. Had you told it
to do a static_cast, it would have complained.

Quote:
Therefore it does a reinterpret cast instead of a static cast.

As the standard says it should.

The new style casts were added for a reason. Use them.

Quote:
Consider the following code:
A * a = new C();
a->a = 50;
printf("A: %d, C: %d", a->a, a->getAasC()->c)
Depending on how you compiler does the reinterpret cast the above will
either segfault or print:
A: 50, C: 50
My compiler didn't even give me a warning!

G++ will warn if the proper options are given. (The problem is
that it then also warns in cases where the C style cast is not
so problematic; where it can only have one meaning.)

Quote:
I think it should give you an error if you try to cast
something and it doesn't know how to do the cast.

You said you didn't care how it casted.

Quote:
Has anyone else run into something like this?

I used to run into it all the time. On one project, for various
reasons, we had a very complex inheritance hierarchy. And a
slight change in it sometimes meant that a static_cast suddenly
(and silently) became a reinterpret_cast.

Any code review which allows a C style cast of a pointer or
reference to pass isn't doing its job.

--
James Kanze kanze.james (AT) neuf (DOT) fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Earl Purple
Guest





PostPosted: Wed Jul 19, 2006 4:03 am    Post subject: Re: Foward decleration casting craziness Reply with quote

James Kanze wrote:
Quote:
Any code review which allows a C style cast of a pointer or
reference to pass isn't doing its job.

I use a C-style cast in only 2 cases -

1. when I am casting 0 (will be nullptr in the new standard) and am
casting to tell the compiler which overload to call. (It might be a
template)

In that case there is no real danger as long as a null-pointer is
acceptable of course, and the code does look a bit cleaner.

2. When I am writing a pointer to a stream and casting it to const void
*. Most of the time this is only being done for debugging purpose - I
wouldn't normally write a pointer to a stream for any other purpose.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Guest






PostPosted: Thu Jul 20, 2006 9:28 pm    Post subject: Re: Foward decleration casting craziness Reply with quote

speedplane wrote:
Quote:
Hi there...
I just found a bug in a very well known compiler and I was wondering if
others have found the same problem. Consider the code snippet

class C; // Foward decleration
class A {
public:
// Here we cast to C but we don't know how to cast an A to
C* getAasC{ return (C*)this; };C
int a;
};
Note that this code will compile (in my compiler at least) even though
it does not know how to cast an A to a C. In another file say we define
C:
class B {
public:
int b;
};

class C : public B, A {
public;
int c;
}

In the first code snippet, the compiler does not know how to cast an A
to a C. Therefore it does a reinterpret cast instead of a static cast.
Consider the following code:
A * a = new C();
a->a = 50;
printf("A: %d, C: %d", a->a, a->getAasC()->c)
Depending on how you compiler does the reintpret cast the above will
either segfault or print:
A: 50, C: 50
My compiler didn't even give me a warning! I think it should give you
an error if you try to cast something and it doesn't know how to do the
cast.
Has anyone else run into something like this?
This is not a bug. You are not casting to a "C" but rather to a

"pointer to a C." And the C-style cast used instructs the compiler to
use any casting method (other than dynamic).
In this case it had no choice but to use reinterpret_cast, and hope
that the programmer knows what he is doing.
In other words, it did exactly what you told it to do.

If you want help from the compiler, you will have to tell it what you
are trying to do. In this case, you would write
C* getAasC{ return static_cast<C*>(this); } and if the compiler does
not howl THAT is a compiler bug.
I leave it as a excercise for the reader on how to implement getAasC
correctly, but virtual C* getAasC()=0; comes to mind.....


[ 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
Page 1 of 1

 
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.