Weird V-table issue

H

harsh.murari

In the example below, a single object (Network) is implementing 2
interfaces (INetworkA and INetworkB). Both of these interfaces derive
from the IBase interface (similar to the IUnknown interface of the COM
world). Network object also implements the QueryInterface methods from
IBase interface.

In the main function, I am doing a QueryInterface on the INetworkA
interface. It returns me the pointer to the second interface
INetworkB. On this pointer, if I perform a function of the INetworkB,
the control is jumping into one of INetworkA's functions.

Can anyone tell me why this is happening? The problem goes away if I
am doing a cast when I am returning the interface pointer. But I am
still not convinced that this is the correct behavior by the compiler.
How does casting affect a V-table of a object pointer?

The below program compiles and runs fine on a GNU C++ compiler.


#include <stdio.h>

/* Base Interface */
class IBase
{
public:
virtual int F1() = 0;
virtual int QueryInterface (void **ppOut) = 0;
virtual int QueryInterface2 (void **ppOut) = 0;
};

/* Some interface */
class INetworkA: public IBase
{
public:
virtual int NA() = 0;
virtual int QueryInterface (void **ppOut) = 0;
};

/* Another interface */
class INetworkB: public IBase
{
public:
virtual int NB() = 0;
};

/* This object implements both interfaces */
class Network : public INetworkA,
public INetworkB
{
public:
int F1() { printf("Network::F1()\n"); }
int NA() { printf("Network::NA()\n"); }
int NB() { printf("Network::NB()\n"); }
int QueryInterface (void **ppOut) {*ppOut = this; return 0;}
int QueryInterface2 (void **ppOut) {*ppOut = (INetworkB *) this;
return 0;}
};


int main()
{
Network *netObj = new Network();
INetworkA *pINetA = netObj;
INetworkB *pINetB = netObj;

pINetA->NA();
pINetB->NB();

/* Weirdness happens here */
/* Get the INetworkB interface using QueryInterface() with no
casting */
pINetA->QueryInterface ((void **) &pINetB);
pINetB->NB();

/* Get the INetworkB interface using QueryInterface2() which does
casting*/
pINetA->QueryInterface2 ((void **) &pINetB);
pINetB->NB();

return 0;
}
 
M

Marcel Müller

Hi,

Can anyone tell me why this is happening? The problem goes away if I
am doing a cast when I am returning the interface pointer. But I am
still not convinced that this is the correct behavior by the compiler.
How does casting affect a V-table of a object pointer?

you are happily to void* and then to another pointer type. This is invalid.

The below program compiles and runs fine on a GNU C++ compiler.

Don't use C-style reinterpret casts.
Don't use void* in C++ programs (except for wrapping C library functions).

And while we are at it do not use char* in C++ programs (You did not do
that in the example, of course). But const char* is fine.

If you follow this advices you won't run into that invalid code without
a compiler warning or error.

int QueryInterface (void **ppOut) {*ppOut = this; return 0;}
int QueryInterface2 (void **ppOut) {*ppOut = (INetworkB *) this;

Furthermore these functions are completely superflous, since every class
pointer to an instance of Network is implicitely convertable to a
pointer to all of it's public base classes.

If you want to restrict the interface availibility by some runtime
conditions, derive protected from the interface and write a strongly
typed QueryInterface function that returns NULL or throws an exception
in case of an error.

And even more, when the same interface is implemented at different
levels of the class hierarchy, you should always derive virtual from
the interface. This gives the Java like behavior.

/* Weirdness happens here */
/* Get the INetworkB interface using QueryInterface() with no
casting */
pINetA->QueryInterface ((void **) &pINetB);

You directly assigned a pointer to Network to a pointer to INetworkB.


Marcel
 
J

James Kanze

In the example below, a single object (Network) is
implementing 2 interfaces (INetworkA and INetworkB). Both of
these interfaces derive from the IBase interface (similar to
the IUnknown interface of the COM world). Network object also
implements the QueryInterface methods from IBase interface.
In the main function, I am doing a QueryInterface on the
INetworkA interface. It returns me the pointer to the second
interface INetworkB. On this pointer, if I perform a function
of the INetworkB, the control is jumping into one of
INetworkA's functions.
Can anyone tell me why this is happening? The problem goes
away if I am doing a cast when I am returning the interface
pointer. But I am still not convinced that this is the correct
behavior by the compiler. How does casting affect a V-table
of a object pointer?
The below program compiles and runs fine on a GNU C++ compiler.
#include <stdio.h>
/* Base Interface */
class IBase
{
public:
virtual int F1() = 0;
virtual int QueryInterface (void **ppOut) = 0;
virtual int QueryInterface2 (void **ppOut) = 0;
};
/* Some interface */
class INetworkA: public IBase
{
public:
virtual int NA() = 0;
virtual int QueryInterface (void **ppOut) = 0;
};
/* Another interface */
class INetworkB: public IBase
{
public:
virtual int NB() = 0;
};

One quick question: do you really want two independent instances
of IBase in your hierarchy? Since IBase doesn't contain any
data, it may not matter, but depending on which one you get,
there's no INetworkA or no INetworkB which derives from the
IBase. Almost always, in such cases, you should be deriving
virtually.
/* This object implements both interfaces */
class Network : public INetworkA,
public INetworkB
{
public:
int F1() { printf("Network::F1()\n"); }
int NA() { printf("Network::NA()\n"); }
int NB() { printf("Network::NB()\n"); }
int QueryInterface (void **ppOut) {*ppOut = this; return 0;}
int QueryInterface2 (void **ppOut) {*ppOut = (INetworkB *) this;
return 0;}
};
int main()
{
Network *netObj = new Network();
INetworkA *pINetA = netObj;
INetworkB *pINetB = netObj;

pINetA->NA();
pINetB->NB();

/* Weirdness happens here */
/* Get the INetworkB interface using QueryInterface() with no
casting */
pINetA->QueryInterface ((void **) &pINetB);

And what is the (void**) supposed to be doing.

What it actually does is introduce undefined behavior. Anything
can and will happen. (Note that there's not even a guarantee
that a void* has the same size and representation as an
INetworkB*; I've actually used a machine where a void* was
bigger than a pointer to a class. Which means that when the
code in the function assigns through the dereferenced void**,
it's going to overwrite memory beyond the end of the
INetworkB*.)

From here on out, of course, anything can happen. (In a typical
implementation on a modern architecture, you'll get a pointer to
the complete object in pINetB, and not a pointer to the
INetworkB subclass of the complete object. And since most
compilers will lay out the base classes in the order they
appear, that means a pointer to Network, which will also work
like a pointer to the INetworkA subobject, i.e. the initial part
of the Network vtable is identical to that of INetworkA. But of
course, that's just an artifact of the way it happens to be
implemented; it's not at all guaranteed.)

The only way to do this correctly is to have the interface take
a pointer to the correct type of pointer. Once you pass through
void*, the compiler looses all information concerning the
inheritance hierarchy, and anything can happen.
pINetB->NB();
/* Get the INetworkB interface using QueryInterface2() which does
casting*/
pINetA->QueryInterface2 ((void **) &pINetB);

Same problem as above. In this case, however, since you have
the correct corresponding cast in the function, the only problem
is that you're type punning between an INetworkB* and a void*.
(Which means that it will work *IF* the two have the same size
and representation, which is the case on most modern machines.)
pINetB->NB();
return 0;
}

Drop all of your C style casts. In such cases (navigating in a
hierarchy), you should be using only dynamic_cast. And the
places where the dynamic_cast won't compile are the places where
the C style casts do the wrong thing.
 
J

Joe Greer

(e-mail address removed) wrote in (e-mail address removed):

By an large you don't need this kind of complexity in C++, but assuming for
the moment that you did....
The below program compiles and runs fine on a GNU C++ compiler.


#include <stdio.h>

/* Base Interface */
class IBase
{
public:
virtual int F1() = 0;
virtual int QueryInterface (void **ppOut) = 0;
virtual int QueryInterface2 (void **ppOut) = 0;
};

/* Some interface */
class INetworkA: public IBase
{
public:
virtual int NA() = 0;
virtual int QueryInterface (void **ppOut) = 0;

You don't really need to mention this again. It will be inherited from
IBase.
};

/* Another interface */
class INetworkB: public IBase
{
public:
virtual int NB() = 0;
};

/* This object implements both interfaces */
class Network : public INetworkA,
public INetworkB
{
public:
int F1() { printf("Network::F1()\n"); }
int NA() { printf("Network::NA()\n"); }
int NB() { printf("Network::NB()\n"); }
int QueryInterface (void **ppOut) {*ppOut = this; return 0;}

this will reflect the type of the interface used to call the function. So,
you will always return the same interface which which you called the
QueryInterface() method.
int QueryInterface2 (void **ppOut) {*ppOut = (INetworkB *) this;
return 0;}

For both this method and the previous, you should use dynamic_cast to cast
the pointer to the appropriate type. dynamic_cast will return 0 if the
interface isn't supported,so you can have your return value actually mean
something as well. So, you might have:

int QueryInterface(void **ppOut) { *ppOut = dyanamic_cast<INetworkA *>
(this); return *ppOut == 0; }



I haven't actually compiled the above, but it should work.

The way you have this implemented you don't really accomplish much. It is
much easier to just use static_cast or dynamic_cast directly to get the
interface you want. If the idea as to restrict access to interfaces, then
you need to use private inheritance instead of public and provide methods
to get you going. For example,

class IBase
{ public:
virtual int QueryInteface(void **ppOut) = 0;
virtual int QueryInterface2(void **ppOut) = 0;
};

class INetworkA
{
public:
virtual int NA() = 0;
virtual int QueryInterface2(void **ppOut) = 0;
};

class INetworkB
{
public:
virtual int NB() = 0;
virtual int QueryInterface(void **ppOut) = 0;
};

class Network : public IBase, private INetworkA, private INetworkB
{
public:
int F1() { printf("Network::F1()\n"); }
int QueryInterface(void **ppOut) { *ppOut = dyanamic_cast<INetworkA *>
(this); return *ppOut == 0; }

int QueryInterface2(void **ppOut) { *ppOut = dyanamic_cast<INetworkB *>
(this); return *ppOut == 0; }
private:
int NA() { printf("Network::NA()\n"); }
int NB() { printf("Network::NB()\n"); }
};


int main()
{
Network *netObj = new Network();
// INetworkA *pINetA = netObj; now fails
// INetworkB *pINetB = netObj; now fails

// pINetA->NA();
// pINetB->NB();

INetworkA * pINetA;
INetworkB * pINetB;

/* Get the INetworkA interface using QueryInterface() */
netObj->QueryInterface ((void **) &pINetA);
pINetA->NA();

/* Get the INetworkB interface using QueryInterface2() */
pINetA->QueryInterface2 ((void **) &pINetB);
pINetB->NB();

// Now complete the circuit
INetworkA * pNetA2;
pINetB->QueryInterface((void **) &pINetA2);
pINetA2->NA();

return 0;
}

The above restricts the interfaces so that you have to use one of your
QueryInterfacex() methods and allows movement back and forth via those
methods. The only thing that IBase does for you is makes both the
QueryInterface() methods available from the Network object. I don't know
if that is what you were after, but I hope it helps some anyway.

joe
 
H

harsh.murari

Thanks for all the replies. I do understand that the standard way of
doing things is to use virtual inheritance and dynamic casting.
However, I would like to clarify that I am working on an embedded
environment (and due to some other reasons which I do not want to
detail here), and I am restricted to using non-virtual inheritance and
no dynamic casting.

Further clarification on QueryInterface: I would like to define a
generic method which all the other interfaces inherit. All the
implementation objects implement the QueryInterface() method to return
the interfaces they they implement. In such a scenario, the out-
parameter of the QueryInterface has to be a void **. Is there any
better method of accomplishing what I am trying to do.

Thanks in advance,
Harsh
 
J

Joe Greer

(e-mail address removed) wrote in (e-mail address removed):
Thanks for all the replies. I do understand that the standard way of
doing things is to use virtual inheritance and dynamic casting.
However, I would like to clarify that I am working on an embedded
environment (and due to some other reasons which I do not want to
detail here), and I am restricted to using non-virtual inheritance and
no dynamic casting.

Further clarification on QueryInterface: I would like to define a
generic method which all the other interfaces inherit. All the
implementation objects implement the QueryInterface() method to return
the interfaces they they implement. In such a scenario, the out-
parameter of the QueryInterface has to be a void **. Is there any
better method of accomplishing what I am trying to do.

Thanks in advance,
Harsh

I think the problem is that someone somewhere needs to know the layout
of the virtual tables in the actual class that you are using. That is
what dynamic_cast brings to the table. I suppose you can keep your own
table of pointers to the various interfaces and provide a means to
access it from every interface. Then you could avoid the use of
dynamic_cast. Maybe someone else will have a more clever idea for you
though. The following seems to work:

#include <stdio.h>
#include <string>
#include <map>

class IBase
{ public:
virtual int QueryInterface(std::string const & key , void **ppOut) =
0;
protected:
typedef std::map<std::string, void *> InterfaceMap;
};

class INetworkA
{
public:
virtual int NA() = 0;
virtual int QueryInterface(std::string const & key, void **ppOut) =
0;
};

class INetworkB
{
public:
virtual int NB() = 0;
virtual int QueryInterface(std::string const & key, void **ppOut) =
0;
};

class Network : public IBase, private INetworkA, private INetworkB
{
public:

Network()
{
m_InterfaceMap.insert(std::make_pair("INetworkA", static_cast
<INetworkA *>(this)));
m_InterfaceMap.insert(std::make_pair("INetworkB", static_cast
<INetworkB *>(this)));
}

int F1() { printf("Network::F1()\n"); }

int QueryInterface(std::string const & key, void **ppOut)
{
int found = 0;
InterfaceMap::iterator itFind = m_InterfaceMap.find(key);
if (itFind != m_InterfaceMap.end()) {
*ppOut = itFind->second;
found = 1;
}
return found;
}

private:
int NA() { printf("Network::NA()\n"); return 0;}
int NB() { printf("Network::NB()\n"); return 0;}
InterfaceMap m_InterfaceMap;
};

int main()
{
Network *netObj = new Network();

INetworkA * pINetA;
INetworkB * pINetB;
netObj->QueryInterface ("INetworkA", (void **) &pINetA);
pINetA->NA();

pINetA->QueryInterface ("INetworkB", (void **) &pINetB);
pINetB->NB();

INetworkA * pINetA2;

pINetB->QueryInterface ("INetworkA", (void **) &pINetA2);
pINetA2->NA();

return 0;
}


Obviously, you don't need to use a string as a key, and you can use any
sort of lookup structure you want. This is for illustrative purposes
only. :) In fact, if you have a small fixed number of interfaces, I
would consider an array of void * s as the InterfaceMap and an enum
value as the key. Such as:

enum Interfaces
{
INetworkA,
INetworkB,
InterfaceCount
};

....

class Network : public IBase, private INetworkA, private INetworkB
{
void * m_InterfaceMap[InterfaceCount];
public:
Network() {
m_InterfaceMap[INetworkA] = static_cast<INetworkA *>(this);
m_InterfaceMap[INetworkB] = static_cast<INetworkB *>(this);
// zero out any empty slots
}

int QueryInterface(Interfaces i, void **ppOut) { *ppOut =
m_InterfaceMap; return *ppOut != 0; }

.....

HTH

joe
 
J

James Kanze

Thanks for all the replies. I do understand that the standard
way of doing things is to use virtual inheritance and dynamic
casting. However, I would like to clarify that I am working
on an embedded environment (and due to some other reasons
which I do not want to detail here), and I am restricted to
using non-virtual inheritance and no dynamic casting.
Further clarification on QueryInterface: I would like to
define a generic method which all the other interfaces
inherit. All the implementation objects implement the
QueryInterface() method to return the interfaces they they
implement. In such a scenario, the out- parameter of the
QueryInterface has to be a void **.

Why? In order to use the result, the user must know the type.

Maybe some sort of template function is what you're looking for:

class Network ...
{
public:
template< typename Interface >
bool queryInterface( Interface** result )
{
*result = this ;
return true ;
}
// ...
} ;

The problem with your code is that the QueryInterface throws
away information that the function needs in order to perform
correctly. Consider something like:

INetworkA* pA ;
INetworkB* pB ;

netObj->queryInterface( (void**)pA ) ;
netObj->queryInterface( (void**)pB ) ;

The actual addresses of the INetworkA and INetworkB subclasses
of the Network are different; how can queryInterface know which
one to return if you don't tell him which one is needed. (With
the template version, above, you wouldn't use the (void**) cast,
and two different functions would be called.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,228
Members
46,818
Latest member
SapanaCarpetStudio

Latest Threads

Top