#1
  1. Javascript Samurai
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2003
    Location
    Manitoba
    Posts
    21
    Rep Power
    0

    writing to file (urgent)


    I did a search but couldn't find anything that worked.

    Here's what I'm trying to do.

    I want to write the branches array to the outfile, but one array node at a time.

    However, I get a coredump on the fwrite function

    Here's my code:

    FILE *outfile;

    char *branches[100];

    outfile = fopen("sample.o", "r+w");

    // branches gets a number of strings

    i = 0;

    while( branches[i] != NULL && i < 100) {

    fwrite(&branches. sizeof(branches), 1, outfile);

    i++;
    }

    fclose(outfile);


    Any help is appreciated

    Thanks,

    Havik
  2. #2
  3. Left due to despotic ad-min
    Devshed Beginner (1000 - 1499 posts)

    Join Date
    Jun 2003
    Posts
    1,044
    Rep Power
    14
    It would probably help if you posted an actual code sample (your fwrite call wouldn't compile because the dot in it is spurious).

    However, I'd guess that the problem is that you don't read in the branches array correctly.

    Given a declaration

    char *x[100];


    you need to remember that the values in the x array are uninitialised (i.e. they don't point at anything in particular). Among other things, this means that something simple like

    strcpy(x[i], "Hello");

    yields undefined behaviour (a term that the C and C++ standards define, and basically means anything can happen at this point).

    What you need to do is something like

    x[i] = malloc(10); /* C version */

    x[i] = new char[10]; // C++ version

    strcpy(x[i], "Hello");

    I would guess failure to do the initialisation is the reason for crashing on the fwrite.
  4. #3
  5. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,163
    Rep Power
    2222
    Part of the difficulty in answering questions lies in trying to understand just what is being attempted. As we used to say years before "Short Circuit": "Computers don't do what you want them to do; they only do what you tell them to do." Corollary: it is marital suicide to respond to your cyberphobic spouse's complaints of "why did the stupid computer to that!?" with the truth, "Because that's what you told it to do."

    I assume that you do intend char *branches[100]; to be an array of character pointers, such that you will have up to 100 strings all accessed through branches. Furthermore, I assume that you had initialized branches with an initialization array or by initializing it to all NULLs and then adding strings to it new'ing/malloc'ing to each applicable entry and copying a string to it, such that every single entry in branches either contains a NULL or a pointer to a valid and properly terminated string. In other words, I assume that branches has been set up correctly.

    BTW, if branches is declared outside the scope of a function (has file scope, therefore is of static storage class -- stored in memory), then most compilers initialize it to all zeros at start-up. DO NOT RELY ON THIS BEHAVIOR! Always initialize a variable explicitly if you depend on its initial value; it also makes the code more readable.

    OTOH, if branches is declared inside of a function, then it is of the auto storage class (stored on the stack) and is not initialized and is therefore almost guaranteed to contain garbage. Garbage pointer values are sure death for a program.

    How I would write it (with some program structure for context):
    Code:
    char *branches[100]; 
    void prepare_branches(void);
    void output_branches(void);
    
    int main(void)
    {
        // first, properly initialize branches and load it with valid strings
        prepare_branches();
    
        // now write it out to disk
        output_branches();
    
        return 0;
    }
    
    void output_branches(void)
    {
        FILE *outfile; 
    
        outfile = fopen("sample.o", "r+w"); 
    
        // actually, I would have used a for-loop here, but that's a matter of style
        i = 0; 
        while( branches[ i ] != NULL && i < 100) 
        { 
            // your statement
            // fwrite(&branches. sizeof(branches), 1, outfile); 
            // how I would do it using fwrite
            fwrite(branches[ i ], sizeof(char), strlen(branches[ i ])+1, outfile); 
            i++; 
        } 
    
        fclose(outfile); 
    }
    Discussion:
    You are writing strings out to the disk file. A string is access by a pointer. fwrite is looking for a pointer and branches[ i ] is already a pointer so no address operator is needed.

    Besides which, there is some confusion as to just what you are pointing to with &branches. A recent thread here indicates that &branches would be the same as &branches[0]. So if you write &branches out to disk, then you will be writing all the pointers, not the string data that each one is pointing to. Pointer values have no meaning outside of the program that they are being used in; I can think of no valid reason to write a pointer value out to disk -- outside of logging a pointer error or a heap-usage study, maybe. branches[0] is the pointer to the first string, branches[1] is the pointer to the second string, etc. Therefore, branches[ i ] is the variable you want to pass to fwrite so that you will write out the string data itself.

    Normal usage of the size and count arguments of fwrite and similar functions is that size is the size of the data type and count is how many items of this data type. The data type is char whose length is one. I used the sizeof() function to illustrate this point.

    strlen() returns the length of the string minus the null terminator. I assumed that within the output file you would want to have a delimiter between the strings, that you would want to separate them with a special marker. For this, I decided to use the NULL, so I simply extended the count by one to include it. You might want to use a different delimiter.

    BTW, by not specifying whether you are opening the file in text mode or binary mode, you are allowing it to default to whatever _fmode is (according to Visual C++6 help). This is text by default (again according to VC++6; actual performance may vary between different compilers). To open a file explicitly in text or binary mode, include in the mode parameter a 't' or a 'b'.

    fwrite is normally used for binary files. For a text file, I would have used fprintf:
    fprintf(outfile,"%s\n",branches[i]);
    Here, I separated the strings by putting each one on its own line in the text file. You could also choose to use commas or also use quote marks, etc.

    As for what exactly caused core to dump, I couldn't say. Looks like it probably got hold of a bad pointer.
    Last edited by dwise1_aol; June 14th, 2003 at 12:06 PM.

IMN logo majestic logo threadwatch logo seochat tools logo