Thread: C++ Classes and Binary I/O

  1. #1
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657

    C++ Classes and Binary I/O

    I was recently reading up streams when this thought struck me.

    If I use read/write to backup or restore objects to/from a stream(..and thus files ..etc);
    Is the program prone to the same sort of bugs (or others..) originating from the default copy constructor not being sufficient?
    If yes(as it probably is), is there a work around if Binary I/O is a must ?
    I thought about overloading the >> and << operators of the class directly, but the whole thing feels rather clumsy.

    Also.. is structure padding, in any way, relevant here ?
    Last edited by manasij7479; 09-13-2011 at 07:01 AM.

  2. #2
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by manasij7479 View Post
    If I use read/write to backup or restore objects to/from a stream(..and thus files ..etc);
    Is the program prone to the same sort of bugs (or others..) originating from the default copy constructor not being sufficient?
    If yes(as it probably is), is there a work around if Binary I/O is a must ?
    Depends.

    It is one thing for a particular object to dump its state to a file and then retrieve that state. That is equally easy whether you are using binary or text I/O.

    It is quite another if, on reading from a file, you need to determine the type of object being read. Then you need to interpret the file content, create an object of appropriate type, and then retrieve the state of the newly created object. There is no point in writing a Cat to a file and retrieving an object of type Dog. The challenges to address that, however, are the same whether you are using binary or text I/O. The key is to write information to identify the type to the file, and the state data (often one after the other). Then reading interprets the type information, creates an object of identified type, and then loads the state data. If you get that wrong, you will get problems akin to the problems of doing a shallow copy when a deep copy is required.
    Quote Originally Posted by manasij7479 View Post
    I thought about overloading the >> and << operators of the class directly, but the whole thing feels rather clumsy.
    One doesn't typically use insertion (<<) or extraction (>>) operators for binary I/O. They are typically used for text I/O. If you want binary I/O, provide a write() and a read() function, that is distinct from the insertion and extraction operators. You also need the help of some factory mechanism if you need to write and retrieve type information as well as object state data.

    Quote Originally Posted by manasij7479 View Post
    Also.. is structure padding, in any way, relevant here ?
    It shouldn't be. You need to define the output file format to meet your requirements.

    You will not simply fwrite(some_file, (void *)this); to write an object, as that takes all padding and also things like a binary representation of virtual function tables into the file. Those sorts of things mean that only the program that wrote the file is guaranteed to be able to read it.

    Instead, you need to be careful to write type information (if needed) and state information. If an object contains other objects, than the containing object needs to manage the saving and retrieval of the objects it contains.

    If you are writing any data to a file that is compiler specific (struct padding, virtual function tables, a reliance on an unsigned variable being big-endian and size two bytes, floating point variables) then you severely limit chances of being able to retrieve the objects correctly from the file.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  3. #3
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    The key is to write information to identify the type to the file,
    If you are writing any data to a file that is compiler specific..... then you severely limit chances of being able to retrieve the objects correctly from the file.
    Thanks, that cleared up some misconceptions I had.

    Rethinking the problem, now I think that it doesn't really make much sense to do this with raw data; there is nothing to loose when using text streams, right?

  4. #4
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by manasij7479 View Post
    Is the program prone to the same sort of bugs (or others..) originating from the default copy constructor not being sufficient?
    I'm curious as to why needing to write a non-default constructor would ever be called a bug. Surely if it's required to make the code compile then leaving it out is simply a compile-time error, not a bug.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  5. #5
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by iMalc View Post
    I'm curious as to why needing to write a non-default constructor would ever be called a bug. Surely if it's required to make the code compile then leaving it out is simply a compile-time error, not a bug.
    I means the opposite(associated with shallow and deep copying ), which is never caught by the compiler.

  6. #6
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by iMalc View Post
    I'm curious as to why needing to write a non-default constructor would ever be called a bug.
    Neglecting to implement a constructor when it is needed (compiler-supplied default does shallow copy as it copies pointer by value, the class logic requires a deep copy) tends to result in program bugs. For example, two objects containing a pointer to the same dynamically allocated memory, and destructor of both objects will deallocate it.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Conversions between base classes and derived classes
    By tharnier in forum C++ Programming
    Replies: 14
    Last Post: 03-18-2011, 10:50 AM
  2. Classes access other classes local variables
    By parad0x13 in forum C++ Programming
    Replies: 6
    Last Post: 01-14-2010, 04:36 AM
  3. Replies: 0
    Last Post: 11-04-2006, 11:07 AM
  4. Classes with Other Classes as Member Data
    By njd in forum C++ Programming
    Replies: 2
    Last Post: 09-27-2005, 09:30 AM
  5. Help accessing classes and derived classes
    By hobbes67 in forum C++ Programming
    Replies: 8
    Last Post: 07-14-2005, 02:46 PM