#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    3
    Rep Power
    0

    Need help reading binary files


    I am having problems reading a binary file with pointers in the struct, I can read the file when they are no pointers involved but for some reason I cant seem to read the file when I use pointers (I get errors when running). Any suggestions please let me know, I will leave my code down below.

    I am sorry if I did not post the code correctly I am new here and did not have time to understand the forum to well (I usually post on another forum but it is currently down and this problem is really bugging me so quickly made an account and posted my problem here)

    CODE:

    Code:
    #include <stdio.h>
    #include <string.h>
    
    typedef struct
    {
        float *complete;
        float *complete2;
    }TEST;
    
    void writeFile(float*,float*);
    void readFile(TEST*);
    
    int main()
    {
        TEST *end;
    
        float *test;
        float *test2;
    
        /*float *complete;
        float *complete2;*/
    
        float x;
        float x2;
    
        /*float y;
        float y2;*/
    
        x = 0;
        x2 = 0;
    
        /*y = 0;
        y2 = 0;*/
    
        test = &x;
        test2 = &x2;
    
        /*complete = &y;
        complete2 = &y2;*/
    
        scanf("%f", test);
        scanf("%f", test2);
    
        printf("\ntest : %2.2f\n", *test);
        printf("test2: %2.2f\n\n", *test2);
    
        writeFile(test,test2);
        readFile(end);
    
        printf("complete : %2.2f\n", *(end)->complete);
        printf("complete2: %2.2f\n", *(end)->complete2);
    
        return 0;
    }
    
    void writeFile(float*test, float*test2)
    {
        FILE *fp;
        fp = fopen( "savingValues.txt" , "wb" );
    
        fwrite(test ,sizeof(test),1, fp );
        fwrite(test2,sizeof(test2),1,fp);
    
        printf("Values Saved\n\n");
        fclose(fp);
    }
    
    void readFile(TEST *e)
    {
        FILE *ptr_file;
    
        ptr_file=fopen("savingValues.txt","rb");
    
        fread(e->complete, sizeof(e->complete), 1, ptr_file);
        fread(e->complete2,sizeof(e->complete2), 1, ptr_file);
    
        fclose(ptr_file);
    }
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,155
    Rep Power
    2222
    Here's something I wrote recently in response to a similar problem:
    Then add some diagnostic printouts. In the program that creates the file, print out the addresses of array and of the strings that the name fields point to. In the program that "recreates" the array, do the same.

    When you execute a program, it gets loaded into memory where there is a large enough block of free memory. That means that you can never predict where your program will be loaded and hence you cannot predict where any of your data will be in terms of an absolute address (you know its relative location within your program's memory space, but you don't know where that memory space will be placed). When you malloc memory for those name fields to point to, you pull that malloc'd memory out of the heap, which is a region of memory in your memory space set aside just for that purpose; when you execute your program, you cannot predict where that heap will be located.

    So, let's say that array[0].name points to address 0x0002F800 and your heap starts at 0x0002F000. The string there is "Dennis Ritchie". You write array to disk and close the program. Please note that the only place that the actual name information, "Dennis Ritchie", resided was in the heap at location 0x0002F800; the disk file has none of that information except for the memory location it was at. Since you closed the program, that memory space is freed up for the OS to assign to another process. When you run the second program (maybe the next day after you had rebooted the computer), it gets loaded into memory in a different location than the first, so now the heap is at 0x00058000. You read the array data back in and it says that array[0].name points to 0x0002F800. What's in 0x0002F800? If that memory has been used by other processes, it's very likely that "Dennis Ritchie" has been overwritten or else just plain lost by the computer having been powered down (RAM is volatile memory, meaning that it only remembers as long as it's powered up -- "A computer's attention span is only as long as its power cord."). Even worse, 0x0002F800 does not lie within your program's memory space, so when you attempt to access location 0x0002F800 you commit an access violation and the operating system terminates you immediately with extreme prejudice and for just cause.

    What you need to do is to save the string data in the file as well and then when you read the array from the file you need to also read the string data, malloc and store them in the heap, and update the appropriate name fields with the corresponding string's address.

    Or you could change name to a char array so that the string data would be stored within the array. Then you could write the entire array to disk and read it back again later, keeping in mind the caveats about structure padding.
    It is absolutely useless to save pointers to a file. Rather you need to save the data and the structure of the data to the file to be able to reconstruct that structure when you read it in from the file. That is called data serialization, also "marshalling".

    But as useless and foolhardy the idea of writing pointers to a file may be, the actual problem that you are encountering is that end is an uninitialized pointer. It contains garbage, which means it could be pointing anywhere. It might help if you were to think of a pointer as a loaded gun. Using an uninitialized pointer is like being in a room filled with people who mean very much to you and blindly pointing that loaded gun in a completely random direction and firing it. Nobody in their right mind would even consider doing something like that, and yet you just did and you don't understand why it isn't a good idea. In purely computer terms, the OS gave your program a segment of its total memory space; you can access any memory location in your own memory space, but you are forbidden to access any location outside that space, since the rest of the memory belongs to other programs and to the operating system. An uninitialized pointer will more likely than not try to access outside your memory space. Even if you just happen to access inside your own memory space, you are likely to try to access read-only memory. And even if you can access read/write memory inside your own memory space, you will probably overwrite other data, causing "inexplicable behavior."

    malloc some memory to that pointer before you try to use it.

    And writing and reading pointers to and from files is a dumb idea.
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    3
    Rep Power
    0
    I was thinking of initializing those pointers but when looking at some of my older codes I noticed that I never done that when reading a file and the program worked with no problems, but I will see if initializing it would help.
  6. #4
  7. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    3
    Rep Power
    0
    So I initialized and it worked thanks

    Time for me to fix my main program :D

IMN logo majestic logo threadwatch logo seochat tools logo