Programming Forums

Programming Forums (http://www.programmingforums.org/forumindex.php)
-   C++ (http://www.programmingforums.org/forum15.html)
-   -   Stadard C i/o problems with C++ classes (http://www.programmingforums.org/showthread.php?t=13548)

Soulstorm Jul 13th, 2007 1:10 PM

Stadard C i/o problems with C++ classes
 
I am trying to write some code that saves the contents of a C++ class in a file. So, I am experimenting with some C and C++ i/o code, but I am stuck in some things...

Lets say I have the following code:

:

  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. #include <fstream>
  5.  
  6. using std::vector;
  7. using std::string;
  8. using std::cout;
  9.  
  10. struct TestStruct{
  11.         string alpha;
  12.         string beta;
  13.         vector<string> gamma;
  14. };
  15.  
  16. struct TestStruct2 {
  17.         char alpha[32];
  18.         char beta[32];
  19. }
  20.  
  21. int main (int argc, char* argv[]) {
  22.  
  23.         TestStruct *kkk = new TestStruct;
  24.         kkk->beta = "hello world!";
  25.         kkk->alpha = "hello again!";
  26.         kkk->gamma.push_back("hello third");
  27.         kkk->gamma.push_back("hello fourth!!!");
  28.  
  29.         FILE *fp = fopen("myfile.soul","wb");
  30.  
  31.         fwrite(kkk,sizeof(TestStruct),1,fp);
  32.         fclose(fp);
  33.         free(kkk);
  34.  
  35.         TestStruct *lll = new TestStruct;
  36.  
  37.         fp = fopen("myfile.soul","rb");
  38.         fread(lll,sizeof(TestStruct),1,fp);
  39.  
  40.         fclose(fp);
  41.         cout << lll->gamma[1];
  42.         free(lll);
  43.  
  44.         return 0;
  45. }


The error I get when I run this code is:

:

SoulFramework(1211) malloc: ***  Deallocation of a pointer not malloced: 0x3007d0; This could be a double free(), or free() called with the middle of an allocated block; Try setting environment variable MallocHelp to see tools to help debug
SoulFramework(1211) malloc: ***  Deallocation of a pointer not malloced: 0x300790; This could be a double free(), or free() called with the middle of an allocated block; Try setting environment variable MallocHelp to see tools to help debug


However, if I use character arrays or something like integers in the struct, the code works just fine.

1)Why? Does that have something to do with classes like std::string and vector that are dynamic?
2)If I definitely want to use those classes with standard C i/o what should I do?
3)If I decide to use C++ i/o, what can I do to store the elements of a class like a vector<customStruct> inside a file? The contents of the customStruct could be integers, floats, or std::strings.

EDIT:
To make myself clear: I have a class, that occupies some memory. Is there any way to save this memory piece into a (binary?) file and then load it the same way? I suppose the file would be unreadable by a text editor, this way.

DaWei Jul 13th, 2007 1:58 PM

Don't mix new with free. Free is for use with malloc. Delete is for use with new.

I would use C++ file I/O and write a serialize method for the class (overload the << operator, for instance).

Soulstorm Jul 13th, 2007 2:24 PM

Quote:

Originally Posted by DaWei (Post 130595)
Don't mix new with free. Free is for use with malloc. Delete is for use with new.

I would use C++ file I/O and write a serialize method for the class (overload the << operator, for instance).

Sorry. In my actual code, I had used the "delete" methods instead of free and had the same problem.

But as stupid as it may sound, my question remains. Why am I getting these errors?

As for your solution... Do you mean I should write a class, overload the << operator for this class and output the result in a stream? Ok, let's say I do this, how do I read them back from the file? Using the >> operator in the same order I have written the data in the first place?

DaWei Jul 13th, 2007 3:13 PM

1) You're getting the errors (the only ones you mention in your post) because the pointer returned by new is not a valid pointer for free. Again, use delete.

2) Yup. The problem with writing the structure out en masse is that padding bytes may or may not be present with different compilers run on different systems. It's a portability issue.

Soulstorm Jul 14th, 2007 6:54 AM

Thanks a lot, Dawei. But:

Quote:

Originally Posted by DaWei (Post 130601)
1) You're getting the errors (the only ones you mention in your post) because the pointer returned by new is not a valid pointer for free. Again, use delete.

:

  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. #include <fstream>
  5.  
  6. using std::vector;
  7. using std::string;
  8. using std::cout;
  9.  
  10. struct TestStruct{
  11.     string alpha;
  12.     string beta;
  13.     vector<string> gamma;
  14. };
  15.  
  16. struct TestStruct2 {
  17.     char alpha[32];
  18.     char beta[32];
  19. };
  20.  
  21. int main (int argc, char* argv[]) {
  22.  
  23.     TestStruct *kkk = new TestStruct;
  24.     kkk->beta = "hello world!";
  25.     kkk->alpha = "hello again!";
  26.     kkk->gamma.push_back("hello third");
  27.     kkk->gamma.push_back("hello fourth!!!");
  28.  
  29.     FILE *fp = fopen("myfile.soul","wb");
  30.  
  31.     fwrite(kkk,sizeof(TestStruct),1,fp);
  32.     fclose(fp);
  33.     delete kkk;
  34.  
  35.     TestStruct *lll = new TestStruct;
  36.  
  37.     fp = fopen("myfile.soul","rb");
  38.     fread(lll,sizeof(TestStruct),1,fp);
  39.  
  40.     fclose(fp);
  41.     cout << lll->gamma[1];
  42.     delete lll;
  43.  
  44.     return 0;
  45. }


Result:

:

[Session started at 2007-07-14 12:58:33 +0300.]
SoulFramework(396) malloc: ***  Deallocation of a pointer not malloced: 0x3007e0; This could be a double free(), or free() called with the middle of an allocated block; Try setting environment variable MallocHelp to see tools to help debug
SoulFramework(396) malloc: ***  Deallocation of a pointer not malloced: 0x3007a0; This could be a double free(), or free() called with the middle of an allocated block; Try setting environment variable MallocHelp to see tools to help debug
hello fourth!!!
SoulFramework has exited with status 0.


Maybe I'm missing something... I think I mentioned that using 'delete' has the same result.

DaWei Jul 14th, 2007 9:04 AM

The vector in kkk holds strings allocated on the heap, which are referred by pointers. What you are storing in the file are the pointers. When you delete kkk, you are deleting the information. The pointers become invalid. When you read the file, you put these invalid pointers in lll. When they get dereferenced during the cout, el puko on el shoes.

Soulstorm Jul 14th, 2007 11:53 AM

I see. Thanks Dawei, it makes much more sense now. Seems to me that the best method is to use classes with overloaded operators to do the hard work.

DaWei Jul 14th, 2007 1:11 PM

Yeah. It's a matter of shallow copy versus deep copy. You'd have the same problem if you instantiated lll and assigned kkk to it. When kkk went away, it'd be bogus. You'd need to write a copy constructor and make a deep copy.

grumpy Jul 15th, 2007 10:21 PM

Yup; it's an issue of deep versus shallow copy.

Another description is that use of fread()/fwrite() and C++ classes often don't mix. A common case where they definitely don't mix are when the C++ classes involved have a non-default copy constructor (which allocate resources, etc). Your TestStruct contains two std::strings and a vector of std::strings, which means it contains multiple objects with non-default copy constructors (std::string has a non-default copy constructor, and std::vector<anything> has a non-default copy constructor, as both strings and vectors dynamically manage memory). Non-default copy constructors, in practice, are usually associated with non-default assignment operators.

If you write such objects out with fwrite() and read them in again with fread(), then you are unlikely to get the original object back in good shape. The error messages about no deallocation of malloc()'ed memory is one potential consequence of that.


All times are GMT -5. The time now is 2:47 AM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC