Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Jul 13th, 2007, 12:10 PM   #1
Soulstorm
Hobbyist Programmer
 
Soulstorm's Avatar
 
Join Date: Jan 2006
Location: Menidi, Athens, Greece
Posts: 239
Rep Power: 3 Soulstorm is on a distinguished road
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:

cpp Syntax (Toggle Plain Text)
  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.
__________________
Project::Soulstorm (personal homepage)

Last edited by Soulstorm; Jul 13th, 2007 at 12:27 PM.
Soulstorm is offline   Reply With Quote
Old Jul 13th, 2007, 12:58 PM   #2
DaWei
Resident Grouch
 
DaWei's Avatar
 
Join Date: Jun 2005
Posts: 6,453
Rep Power: 10 DaWei is on a distinguished road
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).
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code.
Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers
DaWei is offline   Reply With Quote
Old Jul 13th, 2007, 1:24 PM   #3
Soulstorm
Hobbyist Programmer
 
Soulstorm's Avatar
 
Join Date: Jan 2006
Location: Menidi, Athens, Greece
Posts: 239
Rep Power: 3 Soulstorm is on a distinguished road
Quote:
Originally Posted by DaWei View Post
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?
__________________
Project::Soulstorm (personal homepage)
Soulstorm is offline   Reply With Quote
Old Jul 13th, 2007, 2:13 PM   #4
DaWei
Resident Grouch
 
DaWei's Avatar
 
Join Date: Jun 2005
Posts: 6,453
Rep Power: 10 DaWei is on a distinguished road
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.
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code.
Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers
DaWei is offline   Reply With Quote
Old Jul 14th, 2007, 5:54 AM   #5
Soulstorm
Hobbyist Programmer
 
Soulstorm's Avatar
 
Join Date: Jan 2006
Location: Menidi, Athens, Greece
Posts: 239
Rep Power: 3 Soulstorm is on a distinguished road
Thanks a lot, Dawei. But:

Quote:
Originally Posted by DaWei View Post
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.
cpp Syntax (Toggle Plain Text)
  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.
__________________
Project::Soulstorm (personal homepage)
Soulstorm is offline   Reply With Quote
Old Jul 14th, 2007, 8:04 AM   #6
DaWei
Resident Grouch
 
DaWei's Avatar
 
Join Date: Jun 2005
Posts: 6,453
Rep Power: 10 DaWei is on a distinguished road
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.
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code.
Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers
DaWei is offline   Reply With Quote
Old Jul 14th, 2007, 10:53 AM   #7
Soulstorm
Hobbyist Programmer
 
Soulstorm's Avatar
 
Join Date: Jan 2006
Location: Menidi, Athens, Greece
Posts: 239
Rep Power: 3 Soulstorm is on a distinguished road
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.
__________________
Project::Soulstorm (personal homepage)
Soulstorm is offline   Reply With Quote
Old Jul 14th, 2007, 12:11 PM   #8
DaWei
Resident Grouch
 
DaWei's Avatar
 
Join Date: Jun 2005
Posts: 6,453
Rep Power: 10 DaWei is on a distinguished road
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.
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code.
Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers
DaWei is offline   Reply With Quote
Old Jul 15th, 2007, 9:21 PM   #9
grumpy
Programming Guru
 
grumpy's Avatar
 
Join Date: Jun 2005
Location: Adelaide, South Australia
Posts: 1,207
Rep Power: 5 grumpy is on a distinguished road
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.
grumpy is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Could some please explain classes to me... TCStyle C++ 10 Feb 20th, 2006 3:51 PM
What is Lightweight C++? difference in inner classes between C++ and Java? jonyzz C++ 4 Sep 2nd, 2005 9:56 AM
List of classes Dark_Shinobi C++ 8 May 23rd, 2005 3:50 PM
Classes Sane Python 8 Apr 29th, 2005 12:50 PM
C++ Classes - Quick question(s) Delete C++ 8 Apr 7th, 2005 7:38 PM




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 2:09 AM.

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