 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Tobias Wagner Guest
|
Posted: Thu Jun 09, 2005 9:39 am Post subject: RTTI and DLLs |
|
|
I have a DLL which exports some functions, say
class A;
class B;
A* create_A();
B* create_B();
void do_something(A* a, B* b);
This DLL is called from other languages (Delphi).
In do_something I'd like to check if 'a' is really an A* and 'b' is really a
B*.
I tried:
void do_something(A* a, B* b) {
if (not dynamic_cast <A*> (a)) std::cerr << "Error: wrong typen";
But this does not work - obviously at least from the compiler point of
view...
How can I have this kind of "type safty" between different languages?
Do I need to add a typeid variable to all classes?
Cheers,
Tobi
[ 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 Jun 09, 2005 12:36 pm Post subject: Re: RTTI and DLLs |
|
|
Tobias Wagner wrote:
| Quote: | I have a DLL which exports some functions, say
class A;
class B;
A* create_A();
B* create_B();
void do_something(A* a, B* b);
This DLL is called from other languages (Delphi).
In do_something I'd like to check if 'a' is really an A* and 'b' is really a
B*.
I tried:
void do_something(A* a, B* b) {
if (not dynamic_cast <A*> (a)) std::cerr << "Error: wrong typen";
|
Define "doesn't work?"
If you want to check exact type, use typeid. dyanmic_cast just checks
to see if it's dynamically convertable. The above experssion is a nop.
All it does is test to see if a is a NULL pointer.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
msalters Guest
|
Posted: Fri Jun 10, 2005 10:16 am Post subject: Re: RTTI and DLLs |
|
|
Tobias Wagner schreef:
| Quote: | I have a DLL which exports some functions, say
class A;
class B;
A* create_A();
B* create_B();
void do_something(A* a, B* b);
This DLL is called from other languages (Delphi).
In do_something I'd like to check if 'a' is really an A* and 'b' is really a
B*.
|
What else can it be? If anotherlanguage is forcing an X through,
there's
very little you can do about it anyway.
| Quote: | I tried:
void do_something(A* a, B* b) {
if (not dynamic_cast <A*> (a)) std::cerr << "Error: wrong typen";
But this does not work - obviously at least from the compiler point of
view...
|
WIthout seeing your class A, I'd have to guess A doesn't have a
virtual
function. dynamic_cast only works on conversions in an inheritance
relation. Every A object is considered to inherit from A, so the cast
is effectively an identity conversion and is likely to be optimized
out.
It certainly is unlikely to catch an unrelated X.
| Quote: | How can I have this kind of "type safty" between different languages?
|
Not. There's no way you can detect all kind of errenous input. What if
the other language doesn't pass a pointer at all, but an int? Not an
int*, but really an int? That's often equivalent to a
reinterpret_cast
typeid
you invent will try to read some bits from the A*, but reading bits
from
address reinterpret_cast<A*>( 5 ) will simply not work.
HTH,
Michiel Salters
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Tobias Wagner Guest
|
Posted: Fri Jun 10, 2005 10:22 am Post subject: Re: RTTI and DLLs |
|
|
Ron Natalie wrote:
| Quote: | I tried:
void do_something(A* a, B* b) {
if (not dynamic_cast <A*> (a)) std::cerr << "Error: wrong typen";
Define "doesn't work?"
|
It's never an error. Even if a pointer to a random adress is given. It is
casted to an A* and dynamic_cast returns != 0, although *a is garbage.
Example in Delphi:
a, b : Pointer
begin
a := create_A();
b := create_B();
do_something (b, a); // a and b are changed and the DLL should give an
error!
| Quote: | If you want to check exact type, use typeid.
|
I want to check, if at the given adress is an object of type A.
| Quote: | dyanmic_cast just checks
to see if it's dynamically convertable.
The above experssion is a nop.
All it does is test to see if a is a NULL pointer.
|
I know. dynamic_cast is NULL iff the argument is not of the given type.
I thought that with RTTI enabled, each object has an additional field with a
unique type-identifier. With the dynamic_cast statement I want to check if
this identifier has the same identifier as a given type.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
enrique Guest
|
Posted: Fri Jun 10, 2005 10:24 am Post subject: Re: RTTI and DLLs |
|
|
Your question really sounds like a Windows programming question. Your
Delphi app needs to interact with your (C++-generated) DLL via COM.
Check out usenet for related groups that discuss this specifically.
[ 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: Fri Jun 10, 2005 3:46 pm Post subject: Re: RTTI and DLLs |
|
|
In article <d89l24$3be$1 (AT) news2 (DOT) rz.uni-karlsruhe.de>, Tobias Wagner
<none (AT) rz (DOT) uni-karlsruhe.de> writes
| Quote: | I know. dynamic_cast is NULL iff the argument is not of the given type.
|
Not really, dynamic_cast<T*> (a_ptr) returns a null pointer iff a_ptr
cannot be converted to point to an object of type T. Note that the
actual object pointed to by a_ptr may be a base sub-object of a complete
object that contains another base sub-object of type T. Or put in more
normal terms, dynamic_cast<> is capable of up-casting, down-casting
_and_ cross-casting.
| Quote: | I thought that with RTTI enabled, each object has an additional field with a
unique type-identifier.
|
No, every type with a virtual member has a mechanism for dynamically
identifying the exact type. Other types are dealt with statically.
| Quote: | With the dynamic_cast statement I want to check if
this identifier has the same identifier as a given type.
|
Then do what you want; compare the typeids
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
[ 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: Fri Jun 10, 2005 4:35 pm Post subject: Re: RTTI and DLLs |
|
|
In article <1118343446.388820.225030 (AT) o13g2000cwo (DOT) googlegroups.com>,
enrique <enrique.pineda (AT) gmail (DOT) com> writes
| Quote: | Your question really sounds like a Windows programming question. Your
Delphi app needs to interact with your (C++-generated) DLL via COM.
Check out usenet for related groups that discuss this specifically.
Whilst the motivation was to do with Windows programming, the question |
was very clearly about C++ which is why it was accepted.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Maxim Yegorushkin Guest
|
Posted: Fri Jun 10, 2005 4:36 pm Post subject: Re: RTTI and DLLs |
|
|
On Thu, 09 Jun 2005 16:36:13 +0400, Ron Natalie <ron (AT) spamcop (DOT) net> wrote:
[]
| Quote: | Define "doesn't work?"
If you want to check exact type, use typeid. dyanmic_cast just checks
to see if it's dynamically convertable. The above experssion is a nop.
All it does is test to see if a is a NULL pointer.
|
In addition, to be able to use dynamic_cast, both classes in question must
have a virtual function.
--
Maxim Yegorushkin
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Swampmonster Guest
|
Posted: Sat Jun 11, 2005 10:42 am Post subject: Re: RTTI and DLLs |
|
|
| Quote: | I want to check, if at the given adress is an object of type A.
|
You can't with C++.
| Quote: | dyanmic_cast just checks
to see if it's dynamically convertable.
The above experssion is a nop.
All it does is test to see if a is a NULL pointer.
I know. dynamic_cast is NULL iff the argument is not of the given type.
I thought that with RTTI enabled, each object has an additional field with a
unique type-identifier. With the dynamic_cast statement I want to check if
this identifier has the same identifier as a given type.
|
See above and the other replies to your question - you can't do that
with C++. For all the RTTI stuff to work in C++ you need to have a valid
pointer/type pair to begin with. Then you can test for the concrete
class - i.e. when you have a class hirarchy like in MFC you can test if
a (valid!) CWnd* points to a concrete CButton. Finally, when you pass a
CWnd* to dynamic_cast and cast it to CWnd* again, the compiler assumes
that the CWnd* you pass in is valid, i.e. points to a CWnd (or derived)
object, and just drops the cast - i.e. you will get the exact same value
that you passed in, even if it's garbage.
One solution to your problem might be to store the addresses of all
objects allocated by your DLL inside some container - possibly along
with some form of type-id (either a std::string initialized by
type_info::raw_name() or some other home-brewn id). Then you can (in
each of your DLL's functions) check if the object is known to your DLL
(i.e. look it up in that container which would preferrably be a
(hash)set or (hash)map) and check if the type stored in the container is
what your function expects it to be.
Or just use the handle idiom - but that might be overkill in case you
don't need to hide the address of your objects.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Paul DeRocco Guest
|
Posted: Sat Jun 11, 2005 10:49 am Post subject: Re: RTTI and DLLs |
|
|
| Quote: | "Tobias Wagner" <none (AT) rz (DOT) uni-karlsruhe.de> wrote
I have a DLL which exports some functions, say
class A;
class B;
A* create_A();
B* create_B();
void do_something(A* a, B* b);
This DLL is called from other languages (Delphi).
In do_something I'd like to check if 'a' is really an A* and 'b' is really
a
B*.
I tried:
void do_something(A* a, B* b) {
if (not dynamic_cast <A*> (a)) std::cerr << "Error: wrong typen";
But this does not work - obviously at least from the compiler point of
view...
How can I have this kind of "type safty" between different languages?
Do I need to add a typeid variable to all classes?
|
Both dynamic_cast and typeid are only able to identify the actual derived
class, given a base class pointer, and then only for polymorphic classes. So
casting an A* to an A* is a no-op.
No language mechanism can verify that a typed pointer hasn't been given a
spoofed pointer to something invalid, any more than it can find the actual
type of an object given a void pointer. About the best thing you can do, if
you really need to protect against spoofing, and you're designing the
classes, is to put a member containing a magic number at the beginning of
all your classes, and check that.
--
Ciao, Paul D. DeRocco
Paul mailto:pderocco (AT) ix (DOT) netcom.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Tobias Wagner Guest
|
Posted: Sat Jun 11, 2005 6:29 pm Post subject: Re: RTTI and DLLs |
|
|
Paul DeRocco wrote:
| Quote: | No language mechanism can verify that a typed pointer hasn't been
given a spoofed pointer to something invalid, any more than it can
find the actual type of an object given a void pointer. About the
best thing you can do, if you really need to protect against
spoofing, and you're designing the classes, is to put a member
containing a magic number at the beginning of all your classes, and
check that.
|
That's what I wanted to do: use the typeid as the "magic number".
If someone spoofs me and gives an int instead of an A*, then in many cases at
the address where C++ expects to find the typeid of A will be something which is
different from the typeid of A or one of its descendants.
The only way I could think of testing if the typeid (or magic number) is A or a
descendant, was using dynamic_cast.
Cheers,
Tobi
[ 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
|
Posted: Sun Jun 12, 2005 3:29 pm Post subject: Re: RTTI and DLLs |
|
|
Tobias Wagner wrote:
| Quote: | Ron Natalie wrote:
I tried:
void do_something(A* a, B* b) {
if (not dynamic_cast <A*> (a)) std::cerr << "Error: wrong typen";
Define "doesn't work?"
It's never an error. Even if a pointer to a random adress is
given. It is casted to an A* and dynamic_cast returns != 0,
although *a is garbage.
|
You have an A*. You ask the system if it can be converted to an
A*. What should the system say? Even with dynamic_cast, you
cannot lie to the system, and expect to get anything correct
back.
| Quote: | Example in Delphi:
a, b : Pointer
begin
a := create_A();
b := create_B();
do_something (b, a); // a and b are changed and the DLL should give an
error!
If you want to check exact type, use typeid.
I want to check, if at the given adress is an object of type A.
|
Which is impossible, given the way C++ works. Also unnecessary;
the above call would not compile in C++, since pointers are
typed according to what they point to.
| Quote: | dyanmic_cast just checks to see if it's dynamically
convertable. The above experssion is a nop. All it does is
test to see if a is a NULL pointer.
I know. dynamic_cast is NULL iff the argument is not of the
given type. I thought that with RTTI enabled, each object has
an additional field with a unique type-identifier. With the
dynamic_cast statement I want to check if this identifier has
the same identifier as a given type.
|
First, dynamic_cast only works for polymorphic objects --
objects with at least one virtual function. The typical
implementation puts information in the vtbl, which it uses to
implement dynamic cast. No vtbl, no dynamic_cast. The compiler
accepts the statement if and only if it can prove that the cast
must succeed. (Casting a pointer to its own type always
succeeds.) But also, if the pointer does not point to an object
which has a pointer to the vtbl, the compiler will access random
data. Adding one or more virtual functions will make
dynamic_cast work. But will still not change your example,
since the compiler knows how to convert an A* into an A*
statically, and it knows that the tests in dynamic_cast cannot
fail.
--
James Kanze mailto: [email]james.kanze (AT) free (DOT) fr[/email]
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre 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 |
|
 |
James Kanze Guest
|
Posted: Sun Jun 12, 2005 3:30 pm Post subject: Re: RTTI and DLLs |
|
|
Tobias Wagner wrote:
| Quote: | Paul DeRocco wrote:
No language mechanism can verify that a typed pointer hasn't
been given a spoofed pointer to something invalid, any more
than it can find the actual type of an object given a void
pointer. About the best thing you can do, if you really need
to protect against spoofing, and you're designing the classes,
is to put a member containing a magic number at the beginning
of all your classes, and check that.
That's what I wanted to do: use the typeid as the "magic
number". If someone spoofs me and gives an int instead of an
A*, then in many cases at the address where C++ expects to
find the typeid of A will be something which is different from
the typeid of A or one of its descendants.
|
And in many other cases, attempting to read the magic number
will cause the code to core dump. In practice, most C++
implementations do put a "magic number" at the start of a class,
provided the class has virtual functions; the "magic number" is
chosen (at execution time) so that when dereferenced, it will
point to a table of pointers to the virtual functions and other
type dependant information. But 1) trying to read this magic
number may cause a core dump, if the pointer doesn't point to
what it is suppsed to, and 2) the compiler only reads it when it
actually needs the information behind it -- it knows how to
convert an A* into an A* without any special information, and
will normally not read it in a dynamic_cast of an A* to an A*
(just as it will normally not read it in a dynamic_cast of a
Derived* to a Base*).
| Quote: | The only way I could think of testing if the typeid (or magic
number) is A or a descendant, was using dynamic_cast.
|
If you don't know whether the pointer is valid, you can't
dereference it, which limits somewhat your options. About the
only thing I can think of would be to enrol all of the this
pointers in a set in the constructors, and deenrol them in the
destructors. Then, check if the pointer you are given is
contained in the set.
--
James Kanze mailto: [email]james.kanze (AT) free (DOT) fr[/email]
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre 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 |
|
 |
enrique Guest
|
Posted: Tue Jun 14, 2005 7:38 pm Post subject: Re: RTTI and DLLs |
|
|
I saw lots of feedback on your question. Did you ever figure this out
with a C++ solution? Don't forget to post your results so the rest of
us can benefit from your experience.
Thanks.
epp
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Tobias Wagner Guest
|
Posted: Wed Jun 15, 2005 10:42 pm Post subject: Re: RTTI and DLLs |
|
|
enrique wrote:
| Quote: | I saw lots of feedback on your question.
|
Yes, but unfortunately the answer in short form is: It doesn't work with
standard C++ features.
| Quote: | Did you ever figure this out with a C++ solution?
|
As several authors wrote, the only solution would be to introduce magic
numbers in each of my classes. But then I would have to fiddle around with
derived classes when checking for types.
So I decided to live with the segfaults, if the users of my dynamic library
give the wrong types.
Thanks to anyone for the helpful comments.
Tobi
[ 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
|
|