A 2D array wrapped in a structure

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • hanaa
    New Member
    • Nov 2007
    • 44

    A 2D array wrapped in a structure

    Hello

    This piece of code works. But earlier, I had tried using (res->data[i][j]) in place of p[i][j (in line 40, in the for loop inside main()). And the program used to fail due to an access violation error.

    Then I declared the variable **p within main() and assigned res->data to it. And it worked. Can anyone tell me why using res->data[i][j] didnt work. If u can, please do.

    Code:
    #include<stdio.h>
    //compiled using gcc 3.4.5
    struct sam
    {
    int **data;
    };
    
    struct sam* func()
    {
    int rows=2, columns=2, i, j;
    struct sam r;
    r.data=(int **)malloc(sizeof(int*)*rows);
    for(i=0; i<rows; i++)
     {
      r.data[i]=(int*)malloc(sizeof(int)*columns);
     }
    for(i=0; i<rows; i++)
     for(j=0; j<columns; j++)
     {
     r.data[i][j]=i+j;
     }
    for(i=0; i<rows; i++)
     for(j=0; j<columns; j++)
     {
     printf("%d", r.data[i][j]);
     }
    return &r;
    }
    
    main()
    {
    int i, j, rows=2, columns=2, **p;
    struct sam *res;
    res=func();
    p=res->data;
    printf("\nIn caller");
    for(i=0; i<rows; i++)
     for(j=0; j<columns; j++)
     {
     printf("%d", p[i][j]); 
     } 
    
    }
    Thank you!
  • Banfa
    Recognized Expert Expert
    • Feb 2006
    • 9067

    #2
    The problem is that although you allocate the data for the int** pointer in struct sam r; in func the structure itself is on the stack and only has the lifetime of the function call. You return a pointer to r but by the time the receiving code gets that pointer the struct sam r no longer exists, it was deleted when func returned.


    Never EVER return a pointer to data that is local to the function being called.

    Comment

    • hanaa
      New Member
      • Nov 2007
      • 44

      #3
      If thats the case then p[i][j] should not work too, because its the value of res->data that has been assigned to it. But using p[i][j] shows me the correct values.

      Comment

      • Banfa
        Recognized Expert Expert
        • Feb 2006
        • 9067

        #4
        The short answer is that I don't have to. As soon as you accessed an invalid pointer you invoked undefined behaviour. As soon as you invoke undefined behaviour all bets are off, anything can happen including apparently correct behaviour.

        However I will say more but before I do I must stress that you should not rely on this behaviour because of the reason I stated in my first paragraph.

        The thing is that while res points to a structure that has been destroy, res->data points to data that has been malloc'd (and in fact you leak that memory by never freeing it). If you use res directly then the first printf call writes, legitimately to the piece of stack that res points to destroying the contents of *res and causing the access violation.

        When you use the line

        p=res->data;

        before any other code has been executed to dereference res and copy the malloc'd memory pointer before that value is over written which it is the very next line with a printf function call. So p points to valid malloc'd data while res points to invalid stack data that has been overwritten.

        Comment

        • hanaa
          New Member
          • Nov 2007
          • 44

          #5
          Originally posted by Banfa
          The thing is that while res points to a structure that has been destroy, res->data points to data that has been malloc'd (and in fact you leak that memory by never freeing it).
          But the field 'data' is a part of the structure res. So if res gets destroyed because its a local variable, the contents of the 'data' field should also be destroyed right.. Or is it because data points to malloc'd memory that it is not destroyed?

          Comment

          • Banfa
            Recognized Expert Expert
            • Feb 2006
            • 9067

            #6
            Yes. The field data is destroyed, in fact that is the only thing that is destroyed the content pointed to by res. However data is only a pointer, destroying the pointer does not destroy what it points to.

            Comment

            • hanaa
              New Member
              • Nov 2007
              • 44

              #7
              Thank you Banfa. That helped a lot.

              Comment

              Working...