Thread: memory problem, maybe malloc struct...

  1. #1
    Registered User
    Join Date
    Nov 2004
    Posts
    55

    memory problem, maybe malloc struct...

    Hi all,
    I'm writing a program to read some experimental data from a file, then do some manipulations, and then to write the new data into another file. The program works ok, but after a few datapoints, the program does not read values and prints zeros instead.

    For a single reading, I have the format of "date time value", like the example below:
    Code:
    06/12/2007 04:45:14 142.74
    This is repeated 8 times in a single line (for the 8 different types of measurements), and grows up in rows as the experiment carries on.

    I want to read the broken down date, convert it to seconds since the first data point entry (so as to show the time in secs when the reading was taken), and then print this, along with the actual reading.

    Valgrind shows errors coming from two lines in my program but cannot see what is wrong.... Maybe I'm not allocating correctly memory for my structure, but then again, there's no printed statements due to NULL pointers when I check for them...

    Here's my code, it's very simplified in order to reduce the amount of lines I'm posting.

    Code:
    #include<stdio.h>       /* for input and output */
    #include<stdlib.h>      /* for memory management */
    #include<string.h>      /* for memset */
    #include<time.h>        /* for time related functions */
    
    struct dpnt {
            struct tm timh;
            double value;
    };
    
    int main(void) {
    
            int year=0;                  /* dummy year integer */
            int month=0;                 /* dummy month variable */
            unsigned int nrows=0;        /* rows in data file */
            const unsigned int ncols=8;  /* number of forces being measured */
            unsigned int i=0, j=0;       /* counters */
            struct dpnt **data=NULL;     /* data structure, ie time-value datasets */
            FILE *fp=NULL;               /* pointer to file to read data */
            FILE *newfp=NULL;            /* pointer to file to write data */
            char tempbuff[21];           /* temporary string */
            char templine[700];          /* temporary line */
    
            /* open files */
            fp=fopen("few.orig.data.dat","r");
            newfp=fopen("test","w");
    
            /* count the number of data lines */
            while (fgets(templine,sizeof(templine),fp)!=NULL) {
                    nrows++;
            }
    
            /* allocate 2d structure array */
            data=malloc(nrows*sizeof(*data));
            if (data==NULL) {
                    printf("\nCould not allocate array of pointers");
                    exit(1);
            }
            for (i=0; i<nrows; i++) {
                    data[i]=malloc(ncols*sizeof(*data[i]));
                    if (data[i]==NULL) {
                            printf("\nCould not allocate structure array data[%u]", i);
                            exit(1);
                    }
            }
    
            /* import data from file into appropriate storage types */
            rewind(fp);
            for (i=0; i<nrows; i++) {
                    for (j=0; j<ncols; j++) {
                            fscanf(fp,"%i%*c%i%*c%i %i%*c%i%*c%i %lf", &data[i][j].timh.tm_mday, &month,
                                           &year, &data[i][j].timh.tm_hour, &data[i][j].timh.tm_min,
                                           &data[i][j].timh.tm_sec, &data[i][j].value);
                            data[i][j].timh.tm_mon=month-1;
                            data[i][j].timh.tm_year=year-1900;
                    }
            }
    
            /* write data into new file */
            for (i=0; i<nrows; i++) {
                    for (j=0; j<ncols; j++) {
                            memset(tempbuff, '\0', sizeof(tempbuff));
                            strftime(tempbuff, 20, "%d/%m/%Y %H:%M:%S", &data[i][j].timh);
                            fprintf(newfp, "%s  %010.0f   %08.2f\t", tempbuff,
                                            difftime(mktime(&data[i][j].timh),mktime(&data[0][j].timh)),
                                            data[i][j].value);
                    }
                    fprintf(newfp, "\n");
            }
    
            /* clean up memory */
            for (i=0; i<nrows; i++) {
                    free(data[i]);
            }
            free(data);
            fclose(fp);
            fclose(newfp);
    
            return 0;
    }
    Valgrind shows the folloing errors for the lines below:
    Code:
    "Conditional jump or move depends on uninitialised value(s)"
    
     strftime(tempbuff, 20, "%d/%m/%Y %H:%M:%S", &data[i][j].timh);
    Code:
    "Conditional jump or move depends on uninitialised value(s)"
     "Use of uninitialised value of size 4"
     "Syscall param write(buf) points to uninitialised byte(s)"
     "Address 0x400AC5E is not stack'd, malloc'd or (recently) free'd"
    
     fprintf(newfp, "%s  %010.0f   %08.2f\t", tempbuff,
                               difftime(mktime(&data[i][j].timh),mktime(&data[0][j].timh)),
                               data[i][j].value);

    Can anyone see what my mistake is?

    Thanks a lot!
    Spiros

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    I can't think of anything specific.

    But
    - the memset is unnecessary, strftime() will append a \0
    - you might want to have a larger buffer, being overly precise doesn't help if the string you generate is 1 char too long. Did you check the return result?
    - initialise ALL the members of your struct tm instances, in case mktime() is using garbage data.
    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.

  3. #3
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Some general observations:

    You might want to check if your files could be opened.

    You don't have to use the temporary variables year and month if you don't want to. You could read into data[i][j].timh.tm_year directly, for example, and then just use
    Code:
    data[i][j].timh.tm_year -= 1900;
    Of course, it's just fine how you have it, too.

    Code:
            char templine[700];          /* temporary line */
    
            /* open files */
            fp=fopen("few.orig.data.dat","r");
            newfp=fopen("test","w");
    
            /* count the number of data lines */
            while (fgets(templine,sizeof(templine),fp)!=NULL) {
                    nrows++;
            }
    
            /* ... */
            rewind(fp);
    What if a line is longer than 700 characters?

    There's an easier way to count the number of lines in a file.
    Code:
    int c;
    while((c = getc(fp)) != EOF) {
        if(c == '\n') nrows ++;
    }
    
    rewind(fp);
    You're doing a nice job with freeing your resources -- which is just as well, since otherwise you'd get even more errors from Valgrind.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  4. #4
    Registered User
    Join Date
    Nov 2004
    Posts
    55
    thanks for your replies.

    I improved the code, by initializing all members of the tm structure, and valgrind now shows no errors, but I'm still getting the same behavior at random points in my datafile!... I also changed how I'm calculating the lines in a file based on dwks' recommendation. The buffer length of 700 I had for a line, was plenty as the length of any line in my file was no more than 300 characters. I played around with this, and other things, but it didn't help. And Salem, I did what you suggested, and near where I'm getting my strange inputs, is where the return value from strftime reduces (eg from 19 to 16) for no reason and then goes back to normal(!) I checked the file I'm reading at these points, and there are no missing data eg.

    I'll try different ideas during the weekend, and I'm sure I'll find the bug at some point!


    Thank you very much for your help!

    Spiros
    Last edited by s_siouris; 07-11-2008 at 08:40 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Converting from C to C++
    By Taka in forum C++ Programming
    Replies: 5
    Last Post: 04-08-2009, 02:16 AM
  2. Link List math
    By t014y in forum C Programming
    Replies: 17
    Last Post: 02-20-2009, 06:55 PM
  3. Problem with linked list and shared memory
    By Sirfabius in forum C Programming
    Replies: 10
    Last Post: 11-10-2008, 04:45 PM
  4. problem with sending array of struct over shared memory
    By jet-plane in forum C Programming
    Replies: 26
    Last Post: 05-10-2008, 04:10 AM
  5. Replies: 10
    Last Post: 05-18-2006, 11:23 PM