Thread: C static variables + dynamic memory allocation

  1. #1
    Registered User
    Join Date
    Oct 2010
    Posts
    3

    C static variables + dynamic memory allocation

    I am a little bit puzzled by the behavior of some static variables. Here's the code:

    Code:
    #include<stdio.h>
    #include<stdlib.h>
    
    double** input_file(int *);
    void read_file();
    
    
    int main()
    {
    int i;
    
    for (i=0;i<4;i++)
    	read_file();
    
    
    return 0;
    }
    
    void read_file()
    {
    double **lance_coord;
    static int file_was_read=0;
    int nlances;
    int i;
    
    if (!file_was_read)
    {
    	printf("here\n");
    	lance_coord=input_file(&nlances);
    	file_was_read=1;
    }
    printf("nlances= %10d\n",nlances);
    for (i=0;i<nlances;i++)
    {
    	printf("%10f %10f %10f\n",*(*(lance_coord+i)),*(*(lance_coord+i)+1),*(*(lance_coord+i)+2));
    }
    }
    
    double** input_file(int *nlances)
    {
    
    double d[3], **lance_coord;
    int i,j;
    FILE *fp;
    char* fname="/home/dralexpe/bas_screamer/C_learning/C_tests/io.txt";
    fp=fopen(fname, "r");
    if (fp==NULL) printf("I/O error\n");
    
    *nlances=0;
    while (!feof(fp))
    {
    	fscanf(fp,"%lf %lf %lf", d,d+1,d+2);
    	(*nlances)++;
    }
    rewind(fp);
    
    lance_coord=(double**)calloc(*nlances,sizeof(double*));
    for (i=0;i<*nlances;i++)
    {
    	fscanf(fp,"%lf %lf %lf",d,d+1,d+2);
    	*(lance_coord+i)=(double*)calloc(3,sizeof(double));
    	for (j=0;j<3;j++)
    	{
    		*(*(lance_coord+i)+j)=*(d+j);
    	}
    
    }
    fclose(fp);
    return lance_coord;
    }
    I am trying to read some coordinates from a file, which is done in function double** input_file(int *nlances). I don't know how many lines of coordinates are there, so I am reading the file and counting lines, then rewind and dynamically allocate an array. After that I am reading it the second time and populate the array **lance_coord, which it's returned. The function read_file tests the static variables; I'd like to read the file only once, then keep the array for subsequent calls. The output looks like this:
    Code:
    [dralexpe@new-screamer C_tests]$ ./ptr.o
    here
    nlances=          5
    -195.874000  56.123500  89.452000
    -8956.123000   4.789650 -456.789451
     78.456000 -12035.458970 -45.458890
    -10256.780000  45.789000 12345.125670
    -5689985.230000  45.200000 10000.265416
    nlances=          5
    -195.874000  56.123500  89.452000
    -8956.123000   4.789650 -456.789451
     78.456000 -12035.458970 -45.458890
    -10256.780000  45.789000 12345.125670
    -5689985.230000  45.200000 10000.265416
    nlances=          5
    -195.874000  56.123500  89.452000
    -8956.123000   4.789650 -456.789451
     78.456000 -12035.458970 -45.458890
    -10256.780000  45.789000 12345.125670
    -5689985.230000  45.200000 10000.265416
    nlances=          5
    -195.874000  56.123500  89.452000
    -8956.123000   4.789650 -456.789451
     78.456000 -12035.458970 -45.458890
    -10256.780000  45.789000 12345.125670
    -5689985.230000  45.200000 10000.265416
    In function read_file() the variable nlances is not static, thus it should not retain its value between function calls, yet it does retain it. Why?

    Another thing is that the pointer **lance_coord, defined in read_file() is pointing at a memory area on the heap, but the pointer itself is not on the heap. What I am thinking is, because I didn't release the memory on the heap with free(), that memory is not released, and the pointer to it should have been lost, causing a memory leak. Apparently, the pointer **lance_coord is pointing at the same area between subsequent calls of the function read_file(), as shown in the output.

    This is just a test program to understand the dynamic memory allocation, I will be using this knowledge for a different application.

    Thank you.

  2. #2
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Presumably nlances retains its value because you're not disturbing the stack between calls, so the value is still there. Ditto for lance_coord.

    Try this:
    Code:
    void another_func(int i)
    {
        printf("another_func: %d\n", i);
    }
    
    int main()
    {
        int i;
        for (i=0;i<4;i++)
        {
            read_file();
            another_func(i); // mess up stack
        }
        return 0;
    }
    Also, nlances is counting one-too-many because of improper loop control.
    This:
    Code:
    *nlances=0;
    while (!feof(fp))
    {
        fscanf(fp,"%lf %lf %lf", d,d+1,d+2);
        (*nlances)++;
    }
    Should be like this:
    Code:
    *nlances=0;
    while (fscanf(fp,"%lf %lf %lf", d,d+1,d+2) == 3)
    {
        (*nlances)++;
    }
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  3. #3
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by dralexpe View Post
    I am trying to read some coordinates from a file, which is done in function double** input_file(int *nlances). I don't know how many lines of coordinates are there, so I am reading the file and counting lines, then rewind and dynamically allocate an array. After that I am reading it the second time and populate the array **lance_coord, which it's returned. The function read_file tests the static variables; I'd like to read the file only once, then keep the array for subsequent calls.
    Look into using realloc. You allocate enough for a handful of lines to begin with, and if you need more, you allocate more. realloc retains the previously allocated memory contents, starting at the same address, and "extends" it to the new size. Remember to use a temp pointer to store the return value of realloc, so you don't have a memory leak if it fails (any good tutorial will cover this).

    In function read_file() the variable nlances is not static, thus it should not retain its value between function calls, yet it does retain it. Why?
    Sheer dumb luck. Nothing else has overwritten the spot in memory where it was last time you called the function, and it ends us using the very same memory address on subsequent calls (or another address that contains the same value). Since you do absolutely nothing else that touches the stack between calls to read_file, most likely, all the variables end up in exactly the same place, "initialized" (bogusly) to the same values as they had last time. Try initializing nlances to something else in the declaration (like 2), or call some dummy function that declares a bunch of local variables, and you'll see it doesn't retain the value the way you think.

    Another thing is that the pointer **lance_coord, defined in read_file() is pointing at a memory area on the heap, but the pointer itself is not on the heap. What I am thinking is, because I didn't release the memory on the heap with free(), that memory is not released, and the pointer to it should have been lost, causing a memory leak. Apparently, the pointer **lance_coord is pointing at the same area between subsequent calls of the function read_file(), as shown in the output.
    Same thing, sheer dumb luck. Nothing else has overwritten that portion of memory on the stack, so subsequent calls end up with the same address in there. If you don't free it at the end of read_file, and you don't retain it through a static or global variable, and you don't pass it back to the calling function (main) in any way, then you have a memory leak.

  4. #4
    Registered User
    Join Date
    Oct 2010
    Posts
    3
    Thank you very much, you guys gave me the solution.
    I appreciate you taking the time to help me out.

    Best regards.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 7
    Last Post: 11-18-2011, 07:49 PM
  2. Static memory allocation
    By jimhuf in forum C Programming
    Replies: 5
    Last Post: 10-07-2010, 11:34 AM
  3. Static Memory allocation
    By p3rry in forum C Programming
    Replies: 25
    Last Post: 12-23-2008, 08:30 AM
  4. Dynamic memory allocation
    By Luciferek in forum C++ Programming
    Replies: 118
    Last Post: 10-02-2008, 11:34 AM
  5. Memory dynamic allocation
    By elvio.vicosa in forum C Programming
    Replies: 8
    Last Post: 10-16-2007, 03:30 AM