vtable pointers and default copy constructors..

M

Martijn van Buul

Hi.

I'm having a peculiar problem at work. I've been googling for it, but haven't
found an authorative answer. In a nutshell (Long story follows),
what I'd like to know is:

If I have a C++ class which has several virtual functions and several
member variables, will the default copy constructor also copy the virtual
table pointer, or will it merely do a (shallow) copy of the member variables?
I'm using gcc 4.1.1

(long version)

I work in the machine vision industry. Our systems consist of PC-style
computers, running a small proprietary RT os offering only the most basic
functionality. Most importantly, it's not really multi- processor, -core or
-threading aware, and support for this technology has been shoe-horned in by
running a second instance of the OS on the second core/cpu. Image capturing and
other IO is done on the first CPU, the actual processing is done round-robin on
what CPU time is still remaining on CPU#1 and on CPU#2. The problem originates
from the fact that communication between CPU #1 and #2 isn't clean, and objects
get passed by reference instead of value. This was done because of efficiency
considerations. This means that objects can be created on CPU #1, but executed
on CPU#2. This works OK with "simple" classes using no virtual functions,
templates or whatsoever, but wreaks havoc with classes that do. The instant
CPU#2 hits a virtual function, it will resolve this function using the supplied
vtable, which will contain pointers to the codespace of CPU#1, since it was
instantiated on this context, resulting in an access exception. So far, the
guideline has been simple: "Don't use virtual functions in any object that can
migrate from one CPU to another", but I'm currently facing a problem which
would greatly benefit from having virtual functions - so I'm trying to work
around this restriction. I should point out that, since the real-time nature of
the machine, there is no garbage collection nor virtual memory - especially on
cpu #2 - so anything involving dynamic memory allocation is off.

My current workaround (I'm going to be expelled from the church of good
software design) involves making a fresh new instance of my class on
CPU2 by means of a local instance, and carefully copy over all member
variables (Most of them being pointers to the actual data) individually.
This has the desired effect (since it's being instantiated on the right
CPU it has a correct vtable), but it is cumbersome to maintain and a
potential source of future bugs. At the same time, this is more or less
exactly what a default copy constructor would do: a shallow copy of all
members. This would eliminate the chance of 'forgotten' member variables
not being copied, but at the same time it will only work if it will not
touch the vtables of both objects involved.

So, my question remains:

If I have a C++ class which has several virtual functions and several
member variables, will the default copy constructor also copy the virtual
table pointer, or will it merely do a (shallow) copy of the member variables?
I'm using gcc 4.1.1
 
A

Alf P. Steinbach

* Martijn van Buul:
I'm having a peculiar problem at work. I've been googling for it, but haven't
found an authorative answer. In a nutshell (Long story follows),
what I'd like to know is:

If I have a C++ class which has several virtual functions and several
member variables, will the default copy constructor also copy the virtual
table pointer, or will it merely do a (shallow) copy of the member variables?
Compiler-specific.


I'm using gcc 4.1.1

Check that compiler's implementation if you want to bind yourself to
that particular version of that particular compiler.

(long version)

I work in the machine vision industry. Our systems consist of PC-style
computers, running a small proprietary RT os offering only the most basic
functionality. Most importantly, it's not really multi- processor, -core or
-threading aware, and support for this technology has been shoe-horned in by
running a second instance of the OS on the second core/cpu. Image capturing and
other IO is done on the first CPU, the actual processing is done round-robin on
what CPU time is still remaining on CPU#1 and on CPU#2. The problem originates
from the fact that communication between CPU #1 and #2 isn't clean, and objects
get passed by reference instead of value. This was done because of efficiency
considerations. This means that objects can be created on CPU #1, but executed
on CPU#2. This works OK with "simple" classes using no virtual functions,
templates or whatsoever, but wreaks havoc with classes that do. The instant
CPU#2 hits a virtual function, it will resolve this function using the supplied
vtable, which will contain pointers to the codespace of CPU#1, since it was
instantiated on this context, resulting in an access exception. So far, the
guideline has been simple: "Don't use virtual functions in any object that can
migrate from one CPU to another", but I'm currently facing a problem which
would greatly benefit from having virtual functions - so I'm trying to work
around this restriction. I should point out that, since the real-time nature of
the machine, there is no garbage collection nor virtual memory - especially on
cpu #2 - so anything involving dynamic memory allocation is off.

One conclusion from the above is that the two processors in their
current configuration don't share code memory but do share at least some
data memory.

What you can do is to pass just data, C++ POD objects.

Or you can do other things which is impossible to say since you don't
describe the (limitations of) the system, but I don't think that belongs
in clc++.
 
J

Jerry Coffin

[email protected] says... said:
If I have a C++ class which has several virtual functions and several
member variables, will the default copy constructor also copy the virtual
table pointer, or will it merely do a (shallow) copy of the member variables?
I'm using gcc 4.1.1

The vtable pointer (if the compiler uses such a thing at all) is a
characteristic of the class. It'll be generated as part of
constructing a new object, but whether it's copied from the existing
instance or created anew is hard to guess.

The copy of member variables won't necessarily be shallow. It does a
member-wise copying, so if the members define copy constructors with
"deep" semantics, those will be used. If you have (for example) raw
pointers, a "shallow" copy will be made of those.
 
T

Thomas J. Gritzan

Martijn said:
If I have a C++ class which has several virtual functions and several
member variables, will the default copy constructor also copy the virtual
table pointer, or will it merely do a (shallow) copy of the member variables?
I'm using gcc 4.1.1

Well, usually, the copy constructors don't copy your vtable (or whatever
your compiler uses), because a copied object has the static type you
construct it with.

Example:

struct base { /* some virtual functions */ };
struct sub : base { /* some virtual functions */ };

sub s;
base b = s;

b is copy constructed from s, but b is of type base, not of type sub.

I hope that's clear enough :)
 
M

Martijn van Buul

It occurred to me that Alf P. Steinbach wrote in comp.lang.c++:
* Martijn van Buul:

Compiler-specific.

Hrmpf.

I decided to avoid the issue, and only pass data along, at the expense
of some aesthetics. It's not worth creatng potential bugs and future
incompatibilities over.
One conclusion from the above is that the two processors in their
current configuration don't share code memory but do share at least some
data memory.

Correct. CPU #2 only has a relatively small stack and its own code. All
actual data is owned by CPU#1.
What you can do is to pass just data, C++ POD objects.

That's what we've been doing so far, and this is I reverted to doing
again. It's not particulary pretty, but it does the job.

Thanks for the advice, also to the other people who replied.
 
M

Martijn van Buul

It occurred to me that Thomas J. Gritzan wrote in comp.lang.c++:
Example:

struct base { /* some virtual functions */ };
struct sub : base { /* some virtual functions */ };

sub s;
base b = s;

b is copy constructed from s, but b is of type base, not of type sub.

I hope that's clear enough :)

Well, the problem would more be something in the line of:

class Fruit { virtual foo(); ... enum { eApple, eOrange, eKiwi } mType;};

class Apple : public Fruit { ... };
class Orange: public Fruit { ... };
class Kiwi: public Fruit { ... };

{
Fruit *inheritedFruitFromCPU1; // pointer to either an instance of Apple,
// Orange of Kiwi
Apple locallyAllocatedApple;
Orange locallyAllocatedOrange;
Kiwi LocallyAllocatedKiwi;

Fruit *LocallyAllocatedFruit = NULL;

switch(Fruit->mType)
{
case eApple:
{
Apple *originalApple = dynamic_cast<Apple *>(intheritedFruitFromCPU1);
locallyAllocatedApple = *originalApple;
locallyAllocatedFruit = &locallyAllocatedApple;
break;
}
case eOrange:
[...]

etcetera. This in itself is rather ugly, but it's the best I can do lacking
*any* kind of dynamic memory. The stack is the only memory source I have
available.
 

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

Similar Threads


Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top