Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!uunet!microsoft!jimad From: jimad@microsoft.UUCP (Jim ADCOCK) Newsgroups: comp.lang.c++ Subject: Re: I/O problem Keywords: C++ I/O binary Message-ID: <58846@microsoft.UUCP> Date: 6 Nov 90 18:29:44 GMT References: <1179@appli.se> Reply-To: jimad@microsoft.UUCP (Jim ADCOCK) Organization: Microsoft Corp., Redmond WA Lines: 39 In article <1179@appli.se> niklas@appli.se (Niklas Hallqvist) writes: | Is there a way to do portable binary I/O on classes with virtual |functions? Yes, I know there is, by letting the objects them self provide |a binary image via a virtual function. But what I want is to write some- |thing like: | |class A { private: int x; public: virtual int y(void) { return x; }}; |void put(A* a) { write(1, &a, sizeof(a)); } |A* get(void) { A* a = new A; read(0, &a, sizeof(a)); return a; } | |And what happens here? Aha, the vtbl pointer gets saved along with the |binary image, and will be read in by other programs using the get function. |No harm in that, is it? Well, YES!!!! Another program would be differently |laid out in memory and the vtbl ptr would not be valid there. Unpredictable |results will follow the first virtual call. Now don't tell me you can't |do something like this without rewriting all the classes one want to be |able to store this way. The vtable pointer would seem to be just a special case of a general problem -- pointers in general. If you are going to store out objects into a file, then read them back in later at a different address, possibly even into a different program, then you're going to have to do something special to have any pointers in the objects make sense after they are reconstituted. This problem is typically handled by creating some kind of persistent object identifiers for objects on disk, swizzle internal representation pointers to these persistent IDs before writing to a disk, and deswizzle the pointers when the objects are read back in at new locations. Vtable pointers, Vbase pointers, and other nasty bits have to be handled as special cases of this general technique. For example, vtable pointers might be swizzled to a persistent type identifier. |Summary: How would you do if you had a "black box"- |class (i.e no source, just relocatable object code) and wanted to do I/O, |keeping the objects full state (even private info)? My claim would be that without source nor "debugger" info you can't, since you cannot with certainty determine what are the pointers needing to be swizzled to PIDs. This is equivalent to the the problem with conservative garbage collectors -- Since pointers are never identified with certainty, objects cannot be moved.