Thread: Pointers problem

  1. #1
    Registered User
    Join Date
    May 2012
    Location
    Brazil
    Posts
    7

    Question Pointers problem

    Hi there. I'm new to the forum and this is my first time posting here. I'm a newbie at C and I'm experiencing a pointers problem. Here's the code:

    Code:
    #include <stdio.h>
    
    float *mult_matrix(int n, float *p, float *q);
    float *get_matrix(int m, int n);
    void show_matrix(int m, int n, float *p);
    
    int main(void)
    {
        int n;
        float *a, *b, *x;
    
        printf("\nEnter the size of the linear system: \n");
        scanf("%d", &n);
        
        a=get_matrix(n, n);
        show_matrix(n, n, a);
        b=get_matrix(n, 1);
        show_matrix(n, 1, b);
        x=mult_matrix(n, a, b);
        show_matrix(n, 1, x);
    
        return 0;
    }
    
    float *mult_matrix(int n, float *p, float *q)
    {
        int i, j;
        float X[n];
        float *x;    
        
        for(i=0; i<n; i++) {
            X[i]=0;
        }
    
        for (i=0; i<n; i++) {
            for(j=0; j<n; j++) {
                X[i]=X[i]+(*p)*(*q);
                p++;
                q++;
            }    
            q=q-n;
        }
        x=X;
    
        return x;
    }
    
    float *get_matrix(int m, int n)
    {
        int i, j;
        float *a, A[m][n];
        a=&A[0][0];
    
        for (i=0; i<m; i++) {
            for (j=0; j<n; j++) {
                printf("\nEnter with the element a%d%d of the matrix:", i+1, j+1);
                scanf("%f", a);
                a++;
            }    
        }
    
        a=a-m*n;
    
        return a;
    }
    
    void show_matrix(int m, int n, float *p)
    {
        int i, j;
        
        printf("\n");
        for (i=0; i<m; i++) {
        printf("\n");
            for (j=0; j<n; j++) {
                printf(" %f ", *p);
                p++;
            }
        }
        printf("\n");
    }
    It is supposed to be a program that receives a matrix and a vector and multiplies them. It compiles, but when it goes to the function Show_Matrix it shows completely different values, so the result is wrong. I've tried Splint debugger so I go the folling messages:

    Splint 3.1.2 --- 03 May 2009

    matrix.c: (in function main)
    matrix.c:13:2: Return value (type int) ignored: scanf("%d", &n)
    Result returned by function call is not used. If this is intended, can cast
    result to (void) to eliminate message. (Use -retvalint to inhibit warning)
    matrix.c:22:11: Fresh storage a not released before return
    A memory leak has been detected. Storage allocated locally is not released
    before the last reference to it is lost. (Use -mustfreefresh to inhibit
    warning)
    matrix.c:15:2: Fresh storage a created
    matrix.c:22:11: Fresh storage b not released before return
    matrix.c:17:2: Fresh storage b created
    matrix.c:22:11: Fresh storage x not released before return
    matrix.c:19:2: Fresh storage x created
    matrix.c: (in function mult_matrix)
    matrix.c:37:9: Value X[] used before definition
    An rvalue is used that may not be initialized to a value on some execution
    path. (Use -usedef to inhibit warning)
    matrix.c:45:9: Stack-allocated storage x reachable from return value: x
    A stack reference is pointed to by an external reference when the function
    returns. The stack-allocated storage is destroyed after the call, leaving a
    dangling reference. (Use -stackref to inhibit warning)
    matrix.c:43:2: Storage x becomes stack-allocated storage
    matrix.c:45:9: Returned storage x not completely defined (*x is undefined): x
    Storage derivable from a parameter, return value or global is not defined.
    Use /*@out@*/ to denote passed or returned storage which need not be defined.
    (Use -compdef to inhibit warning)
    matrix.c:43:2: Storage *x allocated
    matrix.c: (in function get_matrix)
    matrix.c:57:4: Return value (type int) ignored: scanf("%f", a)
    matrix.c:64:9: Returned storage a not completely defined (*a is undefined): a
    matrix.c:52:2: Storage *a allocated
    matrix.c:3:8: Function exported but not used outside matrix: mult_matrix
    A declaration is exported, but not used outside this module. Declaration can
    use static qualifier. (Use -exportlocal to inhibit warning)
    matrix.c:46:1: Definition of mult_matrix
    matrix.c:4:8: Function exported but not used outside matrix: get_matrix
    matrix.c:65:1: Definition of get_matrix
    matrix.c:5:6: Function exported but not used outside matrix: show_matrix
    matrix.c:80:1: Definition of show_matrix

    Finished checking --- 12 code warnings

    Please, could somebody help me and tell me what's going on? Cheers.

  2. #2
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    I'm going to ignore what splint says. That's a pretty bad idea, but you don't know how to use it and I don't have time to teach you so there is no point in talking about it yet.

    In general there is a lot of bad stuff going on. Your biggest problem is stuff like this:
    Code:
        a=get_matrix(n, n);
    ...
    float *get_matrix(int m, int n)
    {
        int i, j;
        float *a, A[m][n];
        a=&A[0][0];
     
        for (i=0; i<m; i++) {
            for (j=0; j<n; j++) {
                printf("\nEnter with the element a%d%d of the matrix:", i+1, j+1);
                scanf("%f", a);
                a++;
            }   
        }
     
        a=a-m*n;
     
        return a;
    }
    When this function returns, the pointer a is invalid, because the matrix A has fallen out of scope. In other words, a is only valid inside of the function get_matrix. You repeat this mistake in the other function, mult matrix, with the X array and the x pointer. This is undefined behavior, which makes your program unpredictable. It could appear to work on your computer in spite of everything, and break terribly on another computer.

    The appropriate way of handling memory is to allocate it at the start of a function or block, and free it at the end of the block. It looks like to me that you want to use A and X throughout the program, so these variables should be allocated in main, and then passed in as arguments to the other functions.

  3. #3
    Novice
    Join Date
    Jul 2009
    Posts
    568
    Quote Originally Posted by whiteflags View Post
    The appropriate way of handling memory is to allocate it at the start of a function or block, and free it at the end of the block. It looks like to me that you want to use A and X throughout the program, so these variables should be allocated in main, and then passed in as arguments to the other functions.
    Allocating these blocks inside `get_matrix()` and `mult_matrix()`, and then returning a pointer to them would likewise work.
    Disclaimer: This post shows my ignorance at the time of its making. I claim ownership of but not responsibility for all errors in it. Reference at your own peril.

  4. #4
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Quote Originally Posted by msh View Post
    Allocating these blocks inside `get_matrix()` and `mult_matrix()`, and then returning a pointer to them would likewise work.
    Not the way the program is being written right now, no. That actually would make things look completely different.

  5. #5
    Novice
    Join Date
    Jul 2009
    Posts
    568
    Quote Originally Posted by whiteflags View Post
    Not the way the program is being written right now, no. That actually would make things look completely different.
    Some changes would be necessary with either approach. Granted, I think what you propose would actually be easier to do, given the code already written. Touche.
    Disclaimer: This post shows my ignorance at the time of its making. I claim ownership of but not responsibility for all errors in it. Reference at your own peril.

  6. #6
    Registered User
    Join Date
    May 2012
    Location
    Brazil
    Posts
    7
    Quote Originally Posted by whiteflags View Post
    I'm going to ignore what splint says. That's a pretty bad idea, but you don't know how to use it and I don't have time to teach you so there is no point in talking about it yet.

    In general there is a lot of bad stuff going on. Your biggest problem is stuff like this:
    Code:
        a=get_matrix(n, n);
    ...
    float *get_matrix(int m, int n)
    {
        int i, j;
        float *a, A[m][n];
        a=&A[0][0];
     
        for (i=0; i<m; i++) {
            for (j=0; j<n; j++) {
                printf("\nEnter with the element a%d%d of the matrix:", i+1, j+1);
                scanf("%f", a);
                a++;
            }   
        }
     
        a=a-m*n;
     
        return a;
    }
    When this function returns, the pointer a is invalid, because the matrix A has fallen out of scope. In other words, a is only valid inside of the function get_matrix. You repeat this mistake in the other function, mult matrix, with the X array and the x pointer. This is undefined behavior, which makes your program unpredictable. It could appear to work on your computer in spite of everything, and break terribly on another computer.

    The appropriate way of handling memory is to allocate it at the start of a function or block, and free it at the end of the block. It looks like to me that you want to use A and X throughout the program, so these variables should be allocated in main, and then passed in as arguments to the other functions.
    So you suggest to use the functions of dynamic allocation of memory on function main()? On this case, malloc() and then free()?

  7. #7
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Quote Originally Posted by guitarman View Post
    So you suggest to use the functions of dynamic allocation of memory on function main()? On this case, malloc() and then free()?
    That, or you could put A and X on the stack in main(). You don't have to call free() on stack variables. Pick whatever you are the most comfortable with.

  8. #8
    Registered User
    Join Date
    May 2012
    Location
    Brazil
    Posts
    7

    Unhappy

    Quote Originally Posted by whiteflags View Post
    That, or you could put A and X on the stack in main(). You don't have to call free() on stack variables. Pick whatever you are the most comfortable with.
    So, I've tried putting a, x and b on the stack in main() but I'm still having trouble. Please, what I'm doing wrong?

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    float *mult_matrix(int n, float *p, float *q);
    float *get_matrix(int m, int n);
    void show_matrix(int m, int n, float *p);
    
    int main(void)
    {
        int n;
        float *a, *b, *x;
    
        printf("\nEnter the size of the linear system: \n");
        scanf("%d", &n);
    
        a=malloc((n*n)*sizeof(float));
        b=malloc((n)*sizeof(float));
        x=malloc((n)*sizeof(float));
    
        if ((!a)||(!b)||(!x)) {
            printf("\nError in memory solicitation.\n");
            exit(1);
        }    
        
        a=get_matrix(n, n);
        show_matrix(n, n, a);
        b=get_matrix(n, 1);
        show_matrix(n, 1, b);
        x=mult_matrix(n, a, b);
        show_matrix(n, 1, x);
    
        return 0;
    }

  9. #9
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Here's my analysis.
    Code:
    int main(void)
    {
        int n;
        float *a, *b, *x;
     
        printf("\nEnter the size of the linear system: \n");
        scanf("%d", &n);
     
        a=malloc((n*n)*sizeof(float));
        b=malloc((n)*sizeof(float));
        x=malloc((n)*sizeof(float)); /* good so far ... */
    
        a=get_matrix(n, n); /* what happens in here? */
        show_matrix(n, n, a);
        b=get_matrix(n, 1); /* here too? */
    OK so, assuming that get_matrix() hasn't changed, we have:
    Code:
    float *get_matrix(int m, int n)
    {
        int i, j;
        float *a, A[m][n]; /* A is a variable length array from C99 */
        a=&A[0][0]; /* a doesn't point to the memory you allocated in main() anymore */
     
        for (i=0; i<m; i++) {
            for (j=0; j<n; j++) {
                printf("\nEnter with the element a%d%d of the matrix:", i+1, j+1);
                scanf("%f", a);
                a++;
            }   
        }
     
        a=a-m*n; /* odd, but acceptable */
     
        return a; /* the same undefined behavior from earlier */
    }
    Let's look at what happens to x.
    Code:
    float *mult_matrix(int n, float *p, float *q)
    {
        int i, j;
        float X[n]; /* variable length array again */
        float *x;   
         
        for(i=0; i<n; i++) {
            X[i]=0;
        }
     
        for (i=0; i<n; i++) {
            for(j=0; j<n; j++) {
                X[i]=X[i]+(*p)*(*q);
                p++;
                q++;
            }   
            q=q-n; /* odd, but acceptable. */
        }
        x=X; /* memory leak here, x doesn't point to what you malloced anymore. */
     
        return x; /* the same undefined behavior from earlier */
    }
    You can't use malloc AND variable length arrays at the same time. It causes the mistakes I noted. Returning a pointer to an array on the stack will just lead to invalid pointers after the array falls out of scope. Trying to use malloc and variable length arrays at the same time will just cause memory leaks. You really need to pick one or the other. Once you fix what's wrong in these functions you should be able to call them as many times as you want to.

    Finally, you might be asking why I think show_matrix is OK.
    Code:
    void show_matrix(int m, int n, float *p)
    {
        int i, j;
         
        printf("\n");
        for (i=0; i<m; i++) {
        printf("\n");
            for (j=0; j<n; j++) {
                printf(" %f ", *p);
                p++;
            }
        }
        printf("\n");
    }
    It's all OK because you don't do any assignments to p. As long as p points to an array of integers, you will see them.

    I realize this is confusing, but you probably lack a good lesson on what pointers do, so look here before you try to fix it again. See if it clears anything up for you. Binky Pointer Fun Video
    Last edited by whiteflags; 05-09-2012 at 11:37 PM.

  10. #10
    Registered User
    Join Date
    May 2012
    Location
    Brazil
    Posts
    7
    Thanks. It was a great help. Here's the new code:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    float *mult_matrix(int n, float *p, float *q);
    float *get_matrix(int m, int n);
    void show_matrix(int m, int n, float *p);
    
    int main(void)
    {
        int n;
        float *a, *b, *x;
    
        printf("\nEnter the size of the linear system: \n");
        scanf("%d", &n);
    
        a=get_matrix(n, n);
        show_matrix(n, n, a);
        b=get_matrix(n, 1);
        show_matrix(n, 1, b);
        x=mult_matrix(n, a, b);
        show_matrix(n, 1, x);
    
        return 0;
    }
    
    float *mult_matrix(int n, float *p, float *q)
    {
        int i, j;
        float *x;
    
        x=malloc((n)*sizeof(float));    
    
        for(i=0; i<n; i++) {
            *x=0;
            x++;
        }
        x=x-n;
    
        for (i=0; i<n; i++) {
            for(j=0; j<n; j++) {
                *x=*x+(*p)*(*q);
                p++;
                q++;
                x++;
            }    
            q=q-n;
        }
        x=x-n;
    
        return x;
    }
    
    float *get_matrix(int m, int n)
    {
        int i, j;
        float *a;
        
        a=malloc((m*n)*sizeof(float));
    
        for (i=0; i<m; i++) {
            for (j=0; j<n; j++) {
                printf("\nEnter with the element a%d%d of the matrix:", i+1, j+1);
                scanf("%f", a);
                a++;
            }    
        }
    
        a=a-m*n;
    
        return a;
    }
    
    void show_matrix(int m, int n, float *p)
    {
        int i, j;
        
        printf("\n");
        for (i=0; i<m; i++) {
        printf("\n");
            for (j=0; j<n; j++) {
                printf(" %f ", *p);
                p++;
            }
        }
        printf("\n");
    }
    It looks that it is working well, but I have some doubts. Do I have to use free()? What happens to the memory allocated inside functions?

  11. #11
    C lover
    Join Date
    Oct 2007
    Location
    Virginia
    Posts
    266
    You should be free()ing what you malloc()

  12. #12
    Registered User
    Join Date
    May 2012
    Location
    Brazil
    Posts
    7
    Quote Originally Posted by Syscal View Post
    You should be free()ing what you malloc()
    But main() doesnt free it when it returns?

  13. #13
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Quote Originally Posted by guitarman View Post
    But main() doesnt free it when it returns?
    People say that modern operating systems can do that, but it's better just to write complete code. I mean you're depending on that feature. OTOH, free() is standardized.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem with Pointers
    By DeliriumCordia in forum C Programming
    Replies: 19
    Last Post: 03-27-2012, 04:28 PM
  2. Problem with pointers
    By grifan526 in forum C Programming
    Replies: 2
    Last Post: 01-23-2010, 11:49 PM
  3. Problem with pointers
    By kotoko in forum C Programming
    Replies: 3
    Last Post: 06-12-2008, 05:17 AM
  4. Problem with malloc and pointers to pointers
    By mike_g in forum C Programming
    Replies: 7
    Last Post: 03-29-2008, 06:03 PM

Tags for this Thread