Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > type_info, vtable

Reply
Thread Tools

type_info, vtable

 
 
Ivan Vecerina
Guest
Posts: n/a
 
      08-21-2003
"Rolf Magnus" <(E-Mail Removed)> wrote in message
news:bi2aav$qnn$04$(E-Mail Removed)-online.com...
> Ivan Vecerina wrote:
> > How would the C++ run-time handle a failure of this memory allocation
> > without RTTI?

>
> I don't know. Maybe you should ask the gcc developers, since you can
> disable RTTI and still use exceptions in g++.


From what I saw on google, there seems to have been some bugs with
EH when RTTI was disabled. And it's for the best if these were
fixed.

An implementation could also offer a compile mode where dynamic_cast
is supported, but not type_info.

But yes, it would be nice if a compiler writer/maintainer could tell
us if run-time type identification in EH and dynamic_cast share
some common code...


Regards,
--
http://www.post1.com/~ivec



 
Reply With Quote
 
 
 
 
Alf P. Steinbach
Guest
Posts: n/a
 
      08-21-2003
On Thu, 21 Aug 2003 17:22:38 GMT, http://www.velocityreviews.com/forums/(E-Mail Removed) (tom_usenet) wrote:

>On Thu, 21 Aug 2003 16:19:41 GMT, (E-Mail Removed) (Alf P. Steinbach)
>wrote:
>
>>So in your view the similarity of a possible implementation of one
>>aspect of RTTI, one the one hand, and the requirements of exception
>>handling, on the other, makes RTTI necessary for exception handling?
>>
>>How?

>
>A runtime lookup, best implemented on types


Pascal is "better" than Java. So there!



>is required to implement exception handling. This is also true of
>dynamic_cast.


Similarity again. Yada yada yada. Did you know, both the earthworm and
George W. are lifeforms, and even more surprising, both are (to the best
of my knowledge) based on an incredibly complex molecule called DNA?



>I'm not saying that dynamic_cast is used to implement exception
>handling, but that the implementation of both will no doubt use common
>facilities, since matching a catch block is very similar to checking a
>dynamic_cast. Do you agree?


Of course not, since it's illogical.

If you replace "will no doubt" with "can", and "is very similar to" with
"has some similarity with", then yes.



>>I just have to say it, because it's so appropriate: since the doll is
>>so similar to the person, sticking needles into the doll will harm the
>>person. *Sticking needle into a Tom Usenet doll*. Uh, troll?

>
>And you think I'm trolling!?


Yep, I'm 99% sure now.



>...
>I was simply disagreeing with your earlier assertions that matching
>throws with catches, and using dynamic_cast, are completely different
>(something about compile time vs runtime that Ivan and I disagreed
>with).


As we have established, they are very different.

Matching a throw with a catch involves a stack walk; using a dynamic_cast
does not. Checking whether a given throw is compatible with a given catch
can always be done at compile time. That is not the case for a dynamic_cast.
And so on and so forth. How can this be so difficult to grasp?

You'll have to quote the statement of mine which was sufficiently
unclear about that that it could be interpreted as something else.



>They aren't - they are conceptually very similar


No. See immediately above, and the thread in general. However, checking
whether a given throw is compatible with a given catch is conceptually
somewhat similar to a dynamic_cast.

But again, similarity at an abstract level between a part of A and
a part of B does not make A necessary for B.



>and
>implementing the infrastructure for one should give you quite a lot of
>the infrastructure required by the other.


No. It can, but won't necessarily. In particular, a simple throw/catch
compatibility table, computed from compile-time symbol table information,
is presumably of little or no use in implementing dynamic_cast.

 
Reply With Quote
 
 
 
 
Alf P. Steinbach
Guest
Posts: n/a
 
      08-21-2003
On Thu, 21 Aug 2003 19:40:36 +0200, "Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:

>"Alf P. Steinbach" <(E-Mail Removed)> wrote in message
>news:(E-Mail Removed)...
>> On Thu, 21 Aug 2003 15:48:04 GMT, (E-Mail Removed) (tom_usenet)

>wrote:
>> >Right, I agree with that. But, fairly similarly, every constructor
>> >call in a program can be matched with every dynamic_cast statement,
>> >and a matrix produced. This matrix is indexed by constructor call
>> >statements and dynamic_cast statements. Each object stores the
>> >statement (code address) that created it (not necessarily inside the
>> >object).

>>
>> So in your view the similarity of a possible implementation of one
>> aspect of RTTI, one the one hand, and the requirements of exception
>> handling, on the other, makes RTTI necessary for exception handling?

>
>dynamic_cast and type matching in EH both require that instances of
>types that derive from each other can be identified.


That's correct.


>As both of these very similar mechanisms require type identification
>at run time,


That's incorrect.


> is it unreasonable to call them both "RTTI mechanisms" ?


Yes.

 
Reply With Quote
 
Ivan Vecerina
Guest
Posts: n/a
 
      08-22-2003

"Alf P. Steinbach" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> On Thu, 21 Aug 2003 19:40:36 +0200, "Ivan Vecerina"

<ivecATmyrealboxDOTcom> wrote:
....
> >As both of these very similar mechanisms require type identification
> >at run time,

>
> That's incorrect.

....
> > is it unreasonable to call them both "RTTI mechanisms" ?

>
> Yes.


Again, what seems to define type identification for you is
the use of a type identifier associated with an object instance;
using a type identifier associated with a catch block on
the call stack is not.

This is your own definition - feel free:
> >Since "RTTI" is not a term formally defined in the standard,
> >I think it is just pointless to keep arguing.



 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      08-22-2003
On Fri, 22 Aug 2003 06:42:35 +0200, "Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:

>
>"Alf P. Steinbach" <(E-Mail Removed)> wrote in message
>news:(E-Mail Removed)...
>> On Thu, 21 Aug 2003 19:40:36 +0200, "Ivan Vecerina"

><ivecATmyrealboxDOTcom> wrote:
>...
>> >As both of these very similar mechanisms require type identification
>> >at run time,

>>
>> That's incorrect.

>...
>> > is it unreasonable to call them both "RTTI mechanisms" ?

>>
>> Yes.

>
>Again, what seems to define type identification for you is
>the use of a type identifier associated with an object instance;
>using a type identifier associated with a catch block on
>the call stack is not.


Funny, we seem to have posted new replies at the same time...

See my other (new) reply here for what I hope is a clarification.

Of course, it may be that it will only muddle waters even more.



>This is your own definition - feel free:
>> >Since "RTTI" is not a term formally defined in the standard,
>> >I think it is just pointless to keep arguing.


Wasn't that _your_ definition?

 
Reply With Quote
 
tom_usenet
Guest
Posts: n/a
 
      08-22-2003
On Fri, 22 Aug 2003 05:35:17 GMT, (E-Mail Removed) (Alf P. Steinbach)
wrote:

>>> is it unreasonable to call them both "RTTI mechanisms" ?

>>
>>Yes.

>
>The question is : what is the defining characteristic/s of RTTI?
>Pure RTTI seems to be exactly equivalent to 'dynamic_downcast', like,
>say, the Eiffel assignment attempt. But what about that is it that
>makes it "Run Time" (which we've had such a hard time pinning down),
>and what about that is it that makes it "Type Information" (ditto)?
>
>That's a bit subtle, and I agree with Tom Usenet that that is probably
>why we have not managed to agree.
>
>As I see it:
>
>
> "Run Time" --> Only _knowable_ at run time, i.e. potentially
> changing over time for the same code snippet.
>
> "Type Info" --> An _explicit representation_ of a type.
>
>
>I think you all agree with the "Run Time" definition, and probably
>associate "potentially changing" in the context of exception handling
>with "changing catch statement" depending on how a 'throw' is reached.
>
>The "Type Info" is a bit harder, but here's an example, namely the
>'throw'/'catch' compatibility matrix revisited. This matrix is in its most
>basic form indexed by 'throw' statements and 'catch' statements. But in
>typical code the number of thrown types tends to be very small, a handful
>or so, and likewise for the number of caught types. And so all rows
>representing 'throw' statements of the same type can essentially be
>collapsed into one common row, plus an external vector that maps 'throw'
>statements to rows. And ditto for columns indexed by 'catch' statements.
>
>In this optimization a single row that represents a set of 'throw'
>statements of the same type is in effect an identification of that type
>in the sense that there is a one-to-one mapping between the relevant
>types and corresponding rows. But it is not an explicit representation,
>for given the (index to) a row one cannot obtain any information about
>the type except via additional otherwise unnecessary stored associations,
>nor can the row be used for anything but 'catch'/'throw' compatibility
>checking. And the row is not "only knowable at run-time"; it can be (and
>must, in order to practically useful, be) constructed at compile time.
>
>For columns the situation is more complex, for a column index is only
>available when a stack frame with a containing 'catch' has been found.
>So isn't this column index then both an explicit representation of a
>type (the 'catch' type), and only knowable at run-time? Yes to the last,
>but no to the first: it's not an explicit representation, it cannot be
>used to determine anything about the type involved (except via additional
>and otherwise unnecessary information).
>
>In short, all that's necessary for C++ exception handling is _implicit_
>type representation that cannot be used for any other purpose. And so
>it's not surprising that C++ EH cannot emulate 'dynamic_cast'. Or that
>the functionality of 'dynamic_cast', or basic RTTI, is not required.
>
>The end result of this analysis-by-example is that the concept of RTTI
>hinges crucially on _explicit_ type representation.


No, you've shown that exception handling *doesn't* hinge on explicit
type representation. This is also true of dynamic_cast. Here's a
rewrite of your example:

The "Type Info" is a bit harder, but here's an example, namely the
'constructor call'/'dynamic_cast' compatibility matrix revisited. This
matrix is in its most basic form indexed by 'constructor call'
statements and 'dynamic_cast' statements. In typical code the number
of created types tends to be quite large, but the number of types
dynamically casted to tends to be small. And so all rows representing
'constructor call' statements of the same type can essentially be
collapsed into one common row, plus an external vector that maps
'constructor call' statements to rows. And ditto for columns indexed
by 'dynamic_cast' statements.

In this optimization a single row that represents a set of
'constructor call' statements of the same type is in effect an
identification of that type in the sense that there is a one-to-one
mapping between the relevant types and corresponding rows. But it is
not an explicit representation, for given the (index to) a row one
cannot obtain any information about the type except via additional
otherwise unnecessary stored associations, nor can the row be used for
anything but 'dynamic_cast' compatibility checking.

For columns the situation is simple. The column index is known for a
particular 'dynamic_cast' statement at compile time. For rows the
situation is more complex. The row index is only found when the object
begin passed to the 'dynamic_cast' statement is known, and this is
only knowable in general at runtime. So isn't this row index then both
an explicit representation of a type (the 'constructor call' type),
and only knowable at run-time? Yes to the last, but no to the first:
it's not an explicit representation, it cannot be used to determine
anything about the type involved (except via additional and otherwise
unnecessary information).

In short, all that's necessary for C++ dynamic_cast is _implicit_
type representation that cannot be used for any other purpose.


Some very thinking-
>circuit-activating books have been written about just that little
>crucial but hard-to-pin-down difference. Hofstadter's "Gödel, Escher,
>Bach" comes to mind, as well as Scott Fahlman's "NETL", not to mention
>Wolfram's "A new kind of physics". It's no wonder that we find it hard
>to agree on the dividing line...


Your argument is specious, since the fact that exception handling does
not require RTTI can be simply extended to an argument that
dynamic_cast doesn't require RTTI. Either your definition of RTTI is
wrong, or dynamic_cast doesn't require RTTI.

However, neither of these arguments change the fact that matching
catch blocks and performing dynamic_casts both conceptually involve
taking a type, and checking it to see whether it is derived from
another type, and performing this check at runtime.

If your position is simply that you choose not to call that RTTI, we
can agree to disagree.

Tom
 
Reply With Quote
 
Buster Copley
Guest
Posts: n/a
 
      08-22-2003
Dynamic_cast can't be made to work that way.

Exception handling is different. What happens when an exception is
thrown? We know what row of the matrix we need (this information is
encoded in the 'throw', not in the exception object) and we know what
stack frame we are in. We move up a frame until we reach a stack frame
with a catch clause. That gives us a column of the matrix. If the throw
and catch match according to the matrix, we stop. Otherwise we carry on.

Try to use a matrix of object creations to dynamic_casts to emulate
dynamic cast in a similar way. What happens when a constructor is
invoked? What doesn't and couldn't happen is a systematic search for a
dynamic_cast. We know at the point of construction what row of the
matrix to look at, but if we still know that at the dynamic_cast then we
have associated a row-index with each object. Since there is a one-one
correspondence between rows and types, this information can be said to
be type information.

The matrix of object creations and dynamic_casts along with the
row-index to object association could certainly be used to implement
exception handling, but the converse fails. The throw-catch matrix
cannot emulate dynamic_cast, even if extended to include all object
creations and dynamic_casts, because the row-index is not known at the
site of the dynamic_cast.

Corrections are welcome.

Regards,
Buster

 
Reply With Quote
 
tom_usenet
Guest
Posts: n/a
 
      08-22-2003
On Thu, 21 Aug 2003 17:51:55 GMT, (E-Mail Removed) (Alf P. Steinbach)
wrote:

>As we have established, they are very different.
>
>Matching a throw with a catch involves a stack walk; using a dynamic_cast
>does not. Checking whether a given throw is compatible with a given catch
>can always be done at compile time. That is not the case for a dynamic_cast.


You can check, at compile time, whether any particular call to an
object constructor is compatible with any particular dynamic_cast.

>And so on and so forth. How can this be so difficult to grasp?


Because it is factually incorrect! (the bit about dynamic_cast, not
the bit about exceptions).

>
>You'll have to quote the statement of mine which was sufficiently
>unclear about that that it could be interpreted as something else.


To clarify, the statements that you have made that I disagree with:

"With 'dynamic_cast' the argument can be a pointer to an object that
according to the standard must have its dynamic type checked (a
pointer to 'throw' is not checked for dyntype)."

This is inconsistent. The "dynamic type" does not need to be looked up
to perform a dynamic_cast - only an index into a matrix needs to be
computed. According to your definition, this does not count as "having
its dynamic type checked".

Here's another quote (from me and then your response):

"
>What I mean is that there is no fundamental difference between the
>runtime check required by dynamic_cast and the runtime check required
>to select a catch block.
>
>For dynamic cast the compiler could build up a matrix of every use of
>a type in dynamic cast, and every creation of an object.
>
>For exception handling, the compiler could build up a matrix of every
>use of a type in a throw, and every use in a catch.
>
>What's the difference?


The first is nonsense since the type of *p cannot be predicted in the
general case.
"

I disagree with this too.

Your assertion that the type of *p cannot be predicted at compile time
is true. But why do you think that leads to "the first is nonsense"?

My equivalent statement about your throw/catch matrix would be:
"The second is nonsense since the type caught cannot be predicted in
the general case."

But in fact, neither statement is nonsense.

>>They aren't - they are conceptually very similar

>
>No. See immediately above, and the thread in general. However, checking
>whether a given throw is compatible with a given catch is conceptually
>somewhat similar to a dynamic_cast.
>
>But again, similarity at an abstract level between a part of A and
>a part of B does not make A necessary for B.


We're agreed there, but that was never what I was disagreeing with.

>>and
>>implementing the infrastructure for one should give you quite a lot of
>>the infrastructure required by the other.

>
>No. It can, but won't necessarily. In particular, a simple throw/catch
>compatibility table, computed from compile-time symbol table information,
>is presumably of little or no use in implementing dynamic_cast.


On the contrary, the same matrix (with an extra column for each
dynamic_cast target type and an extra row for each created object
type) is fine for dynamic_cast compatibility checks too (ignoring
virtual inheritence for now).

Tom
 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      08-22-2003
On Fri, 22 Aug 2003 11:40:23 GMT, (E-Mail Removed) (tom_usenet) wrote:

>For columns the situation is simple. The column index is known for a
>particular 'dynamic_cast' statement at compile time. For rows the
>situation is more complex. The row index is only found when the object
>begin passed to the 'dynamic_cast' statement is known, and this is
>only knowable in general at runtime. So isn't this row index then both
>an explicit representation of a type (the 'constructor call' type),
>and only knowable at run-time? Yes to the last, but no to the first:
>it's not an explicit representation, it cannot be used to determine
>anything about the type involved (except via additional and otherwise
>unnecessary information).


Just to pin down our differences, it's the "but no to the first", and
the following justification, that I don't agree with.

In my view an address of the constructor call stored in each (non-POD)
object _is_ an explicit type representation, RTTI "Type Information".

And it can easily be used to obtain information about the type, namely
via 'dynamic_cast' to various destination types -- I just note in
passing that if it were not so (which it is) it would not be a working
implementation of 'dynamic_cast'.



>Your argument is specious, since the fact that exception handling does
>not require RTTI can be simply extended to an argument that
>dynamic_cast doesn't require RTTI. Either your definition of RTTI is
>wrong, or dynamic_cast doesn't require RTTI.


Your assertion that dynamic_cast cannot be used to obtain information
about the dynamic type is incorrect, and so that argument is a fallacy.

But that does not mean that the definitions I know of RTTI are
in some sense "correct".

It does, however, mean that any definition of RTTI that doesn't
require storage of an explicit type representation is a practically
useless definition, void of meaning.



>However, neither of these arguments change the fact that matching
>catch blocks and performing dynamic_casts both conceptually involve
>taking a type, and checking it to see whether it is derived from
>another type, and performing this check at runtime.


In my considered opinion George W. requires earthworms, since they
are somewhat similar at the genetic level. Bright insight! Perhaps
he's going fishing?



>If your position is simply that you choose not to call that RTTI, we
>can agree to disagree.


That seems to be the case, yes.

 
Reply With Quote
 
tom_usenet
Guest
Posts: n/a
 
      08-22-2003
On Fri, 22 Aug 2003 13:29:03 +0100, Buster Copley <(E-Mail Removed)>
wrote:

>Dynamic_cast can't be made to work that way.
>
>Exception handling is different. What happens when an exception is
>thrown? We know what row of the matrix we need (this information is
>encoded in the 'throw', not in the exception object) and we know what
>stack frame we are in. We move up a frame until we reach a stack frame
>with a catch clause. That gives us a column of the matrix. If the throw
>and catch match according to the matrix, we stop. Otherwise we carry on.


Right.

>
>Try to use a matrix of object creations to dynamic_casts to emulate
>dynamic cast in a similar way. What happens when a constructor is
>invoked? What doesn't and couldn't happen is a systematic search for a
>dynamic_cast.


Of course not. Two options - either the row number is placed inside
the object, or the address of the object is added to a map of object
address - to row number.

We know at the point of construction what row of the
>matrix to look at, but if we still know that at the dynamic_cast then we
>have associated a row-index with each object. Since there is a one-one
>correspondence between rows and types, this information can be said to
>be type information.


There isn't necessarily such a one-to-one correspondence. If you have
one row per type, then some of the rows may be identical, which makes
the correspondance only many-to-one, strictly speaking.

>The matrix of object creations and dynamic_casts along with the
>row-index to object association could certainly be used to implement
>exception handling, but the converse fails. The throw-catch matrix
>cannot emulate dynamic_cast, even if extended to include all object
>creations and dynamic_casts, because the row-index is not known at the
>site of the dynamic_cast.


It is if the row index is placed inside the object (or its vtable), or
if a map of object address to row index is maintained. This was my
point, that the matrix bit that was being bandied around could also
provide the basis of a dynamic_cast implementation, just as it could
provide the basis of an exception handling implementation. This is
because the matrix is just an implementation of type compatibility,
something that is central to both dynamic_cast and throw/catch
matching.

For an exception, you have to walk the stack to find the column index.
For a dynamic_cast you have to lookup the row index for the object in
question (either inside the object, or in an object address indexed
map). There are different operations, but they are both still runtime
operations (hence my disagreement with assertions about exceptions
being compile time, and dynamic_cast being runtime).

Tom
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
can some one please demystify vtable/vftable Paul C++ 1 06-24-2004 08:43 AM
HELP: wxValidator and undefined reference to `vtable ...` under linux Quansheng Liang C++ 2 05-25-2004 01:17 PM
Undefined symbols: vtable for Foo r C++ 2 08-02-2003 08:18 PM
A::A[not-in-charge]() undefined reference to `vtable for A' Daniel Heiserer C++ 1 08-01-2003 04:05 PM
I am confused with VTable ;-) Pani C++ 2 07-23-2003 10:50 AM



Advertisments