fwrite can't write dynamic strings???

This is a discussion on fwrite can't write dynamic strings??? within the C Programming forums, part of the General Programming Boards category; Hello, I would like to write an array of structs to a binary file. But for some weird reason I'm ...

  1. #1
    * Death to Visual Basic * Devil Panther's Avatar
    Join Date
    Aug 2001
    Posts
    768

    Question fwrite can't write dynamic strings???

    Hello,

    I would like to write an array of structs to a binary file.
    But for some weird reason I'm having problems with the dynamically allocated string.
    It seems to be writing the pointer's address to the file instead of the string itself.

    The following code doesn't write the the struct correctly to the binary file.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    struct stuff {
    	int nameSize;
    	char *name;
    	int num;
    };
    
    int main() {
    
    	struct stuff *myStuff;
    
    	myStuff = (struct stuff *)malloc(sizeof(struct stuff) * 3);
    
    	myStuff[0].name = (char *)malloc(sizeof(char) * 4);
    	strcpy(myStuff[0].name, "abc");
    
    	myStuff[0].nameSize = strlen(myStuff[0].name);
    	myStuff[0].num = 123;
    
    	hFile = fopen("./file.bin", "wb");
    	fwrite(myStuff, sizeof(struct stuff), 1, hFile);
    	fclose(hFile);
    	
    	free(myStuff[0].name);
    	free(myStuff);
    
    	return(0);
    }
    While the below code, works great, except the fact that it writes the full size of the string... ignoring the \0.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    struct stuff {
    	int nameSize;
    	char name[10];
    	int num;
    };
    
    int main() {
    
    	FILE *hFile;
    	struct stuff *myStuff;
    
    	myStuff = (struct stuff *)malloc(sizeof(struct stuff) * 3);
    
    	strcpy(myStuff[0].name, "abc");
    
    	myStuff[0].nameSize = strlen(myStuff[0].name);
    	myStuff[0].num = 123;
    
    	hFile = fopen("./file.bin", "wb");
    	fwrite(myStuff, sizeof(struct stuff), 1, hFile);
    	fclose(hFile);
    	
    	free(myStuff);
    
    	return(0);
    }
    What am I doing wrong?

    Thank you.
    "I don't suffer from insanity but enjoy every minute of it" - Edgar Allen Poe

    http://www.Bloodware.net - Developing free software for the community.

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    fwrite writes whatever you tell it to write. If your struct contains a pointer to a character string, it will write the value of the pointer. Unfortunately, that doesn't work well, since when you read the struct back, the memory is unlikely to be allocated and hold the same value.

    To solve that, you would have to EITHER use statically sized arrays, or use multiple write operations to store your struct, where one write stores the string content.

    Of course, for binary files, it is highly beneficial to have a constant size for each record, so using a fixed size is a good plan in that respect. But it depends on what you are trying to achieve overall.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,047
    How do you know what it is writing without first reading it back with fread()?

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,781
    Quote Originally Posted by itCbitC
    How do you know what it is writing without first reading it back with fread()?
    Examine the file's contents by some other method
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,558
    > It seems to be writing the pointer's address to the file instead of the string itself.
    Which is exactly what it should do, and exactly what is happening.

    Serialisation needs to follow the structure of the data with an equivalent structure in the code. There's no automatic following of pointers.

    Likewise when you read things in, you need to reallocate the memory for the pointer as you read in the "abc" string.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  6. #6
    * Death to Visual Basic * Devil Panther's Avatar
    Join Date
    Aug 2001
    Posts
    768
    Quote Originally Posted by matsp View Post
    fwrite writes whatever you tell it to write. If your struct contains a pointer to a character string, it will write the value of the pointer. Unfortunately, that doesn't work well, since when you read the struct back, the memory is unlikely to be allocated and hold the same value.

    To solve that, you would have to EITHER use statically sized arrays, or use multiple write operations to store your struct, where one write stores the string content.

    Of course, for binary files, it is highly beneficial to have a constant size for each record, so using a fixed size is a good plan in that respect. But it depends on what you are trying to achieve overall.

    --
    Mats
    If I use a statically sized array, let say with 10 cells, and use only 3: abc\0
    It ignores the \0, and writes the all 10 cells: junk.

    Quote Originally Posted by itCbitC View Post
    How do you know what it is writing without first reading it back with fread()?
    It's a test program, a part of a larger application. I know for a fact that it doesn't work.
    "I don't suffer from insanity but enjoy every minute of it" - Edgar Allen Poe

    http://www.Bloodware.net - Developing free software for the community.

  7. #7
    * Death to Visual Basic * Devil Panther's Avatar
    Join Date
    Aug 2001
    Posts
    768
    Quote Originally Posted by Salem View Post
    > It seems to be writing the pointer's address to the file instead of the string itself.
    Which is exactly what it should do, and exactly what is happening.

    Serialisation needs to follow the structure of the data with an equivalent structure in the code. There's no automatic following of pointers.

    Likewise when you read things in, you need to reallocate the memory for the pointer as you read in the "abc" string.
    Ok, so what do you recommend I should do?
    Is there a function that allows me to write a single variable to a binary file? I've looked but was unable to find any
    "I don't suffer from insanity but enjoy every minute of it" - Edgar Allen Poe

    http://www.Bloodware.net - Developing free software for the community.

  8. #8
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,047
    Quote Originally Posted by laserlight View Post
    Examine the file's contents by some other method
    I would like to know how without first rewinding the file and fread()'ing the binary image of the data structure stuff?

  9. #9
    * Death to Visual Basic * Devil Panther's Avatar
    Join Date
    Aug 2001
    Posts
    768
    Quote Originally Posted by itCbitC View Post
    I would like to know how without first rewinding the file and fread()'ing the binary image of the data structure stuff?
    A hex editor?
    "I don't suffer from insanity but enjoy every minute of it" - Edgar Allen Poe

    http://www.Bloodware.net - Developing free software for the community.

  10. #10
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,047
    Quote Originally Posted by Devil Panther View Post
    If I use a statically sized array, let say with 10 cells, and use only 3: abc\0
    It ignores the \0, and writes the all 10 cells: junk.
    That's because fwrite() transfers the binary image of the stuff data structure and it doesn't care about how strings are represented.

  11. #11
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,781
    Quote Originally Posted by Devil Panther
    If I use a statically sized array, let say with 10 cells, and use only 3: abc\0
    It ignores the \0, and writes the all 10 cells: junk.
    That would be fine: after all, when you read back from file, you can ignore whatever is after the null character, as is the normal approach for null terminated strings. Alternatively, you can store the amount of space used.

    Quote Originally Posted by itCbitC
    I would like to know how without first rewinding the file and fread()'ing the binary image of the data structure stuff?
    One way would be to open the file in a hex editor.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  12. #12
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,047
    Quote Originally Posted by laserlight View Post
    One way would be to open the file in a hex editor.
    Cool beans! do you know any good ones for the Unix platform?

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,781
    Quote Originally Posted by itCbitC
    do you know any good ones for the Unix platform?
    Your favourite editor (including vi clones and emacs) may support hex editing, or just need a plugin to augment it with hex editing functionality.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #14
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Also, "od" works well for inspecting binary files - it supports printing in various display formats (e.g. octal, hex, decimal, float(? Never used that)) as well as showing records of various lengths.

    Edit: Of course, it's only useful for VIEWING content. If you actually need to modify the content, I use "hexl-mode" in Emacs or write a program to make the modification (depending on what I'm actually doing...)

    --
    Mats
    Last edited by matsp; 05-18-2009 at 09:35 AM.
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  15. #15
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,047
    I'ave used xxd inside vi but it usually shows some mumbo jumbo, nothing intelligible (on my w/s at least).

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 04-29-2009, 10:13 AM
  2. Help with calloc and pointers to strings.
    By sweetarg in forum C Programming
    Replies: 1
    Last Post: 10-24-2005, 02:28 PM
  3. operator overloading and dynamic memory program
    By jlmac2001 in forum C++ Programming
    Replies: 3
    Last Post: 04-06-2003, 11:51 PM
  4. Dynamic Toolbars
    By nvoigt in forum Windows Programming
    Replies: 1
    Last Post: 01-11-2002, 09:21 AM
  5. array of strings + more
    By null in forum C Programming
    Replies: 10
    Last Post: 10-01-2001, 03:39 PM

Tags for this Thread


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21