Solved

C++ objects with virtual function and UNIX shared memory

Posted on 1997-06-03
1
452 Views
Last Modified: 2012-08-14
I want to make some objects in shared memory. These objects have got virtual functions. The first process (server) makes shared memory and objects in it. Other processes attach this memory and use objects. Can I make these processes not copy or fork of server process?
For example:
class a {
public:
   virtual void func();
};

class b : public a {
   virtual void func();
};
...
Server:
char *ptrshare;   // pointer to shared memory
a *ptra=new a;
b *ptrb=new b;
...
memcopy(ptrshare,ptra,sizeof(a));
ptrshare+=sizeof(a);
memcopy(ptrshare,ptrb,sizeof(b));
ptrshare+=sizeof(b);
...

Client :
char *clientptrshare;
a *ptra=(a *)clientptrshare;
ptra->func();  // ?!!!

I tried this in HP UX. class a was in module a.cpp,
b - b.cpp etc.
If I make programs:
CC server.o a.o b.o c.o -o server
CC client.o a.o b.o c.o -o client
That's OK.
CC server.o a.o b.o c.o -o server
CC client.o a.o c.o b.o -o client
That's wrong.
0
Comment
Question by:viaches
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
1 Comment
 

Accepted Solution

by:
cwestin earned 100 total points
ID: 1163813
What was wrong with the last link line?  You've got to be more explicit.

Yes, this can be done without copying or forking(), but I need to know more details.  You also need to be aware that this may not be portable, depending on the solution you choose.

I suspect your problem has to do with the order of the link line.  Do you understand how virtual functions work?  i.e., do you realize that in your class instances, there is an (invisible) pointer, known as the "vtable pointer" to a structure full of function pointers (the vtable)?  The issue is that the address of the vtable may differ in the different binary images.  When you create "server" the vtable for class a is at a certain adress, call it servera.  But in "client" the vtable for the class may reside at a different address, call it clienta.  When you instantiated the class, the instance's vtable was initialized to point to servera.  But servera != clienta.  Therefore, when client tries to invoke a->virtualfunc(), the vtable pointer is pointing somewhere else.

In general, because of this, and some other related problems that crop up with the use of shared libraries, you can't use C++ virtual functions on objects in shared memory unless the binaries are all identical (implying that the vtables will always be at the same address.)  You can however get the same effect by introducing a level of indirection.  I've used this technique before:  I declare the virtual function explicitly.  Declare a structure that contains the function pointers you want virtual:

struct myfuncs
{
  void (*foo)(myclass *pthis, int x, int y);
   int (*bar)(myclass *pthis, char *p);
};

Initialize this structure with your functions.

const myfuncs MyFuncs =
{
  fooFunc, barFunc
};

  You must have an instance of this in each binary that the functions will be called from.  Then, create invocation macros for the virtual functions that look like this:

#define myclassfoo(pthis, x, y) ((*MyFuncs.foo)(pthis, x, y))
#define myclassbar(pthis, p) ((*MyFuncs.foo)(pthis, p))

Use these macros to call your "virtual functions."  This works because in each image, the macro will be using the locally linked reference to the function pointer rather than one in another process.

If you want polymorphism, things get a bit more complicated.  Then, you have to more closely copy the effects of using a real vtable, but without using pointers.  I've also used this technique before.  You have to assign unique integers to each vtable involved.  In your class instance, put an integer variable that will serve as an explicit "vtable index" (instead of a vtable *pointer*.)  When you instantiate the class, set the vtable index appropriately.  Create invocation macros that use the index to index into an array of pointers to vtables such as the one above.  You have to create and initialize the array of vtable pointers in each process, where it will have the correct local values.  Then, the invocation macros look like this:

#define abstractfoo(pthis, x, y) (*((vtable_type *)vtable_array[(pthis)->vtable_index]).foo)(pthis, x, y))

With
const void *vtable_array[] =
{ (void *)foo_vtable, (void *)bar_vtable, ...};

Again, each process will have its own correct local copy of the function pointers and vtables.  This will also work as a technique to make polymorphism work for classes in shared libraries on platforms that load the library into different addresses in each process.

0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…

691 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question