Pointers to a 2d array and manual memory management - C

左心房为你撑大大i 提交于 2020-01-04 21:40:16

问题


I decided it would be a nice challenge to build a library to handle all kinds of matrix calculations, in pure C. Now, even though I have some pretty good experience with Objective-C and Cocoa, my knowledge of C is just what I need to work with Objective-C and not much more. So, for example, I'm familiar with the concept of pointer, arrays, etc in C, but not with malloc and free (ARC is a bliss!). I decided to embrace this project so I can get more C experience (besides having loads of fun doing this, of course!).

So far I have a matrix defined like this:

typedef float mReal;

typedef struct {
    mReal **v;
    int w;
    int h;
} matrix;

Of course, I also need a method to get me a brand new matrix with the size I want:

void new_matrix(matrix *m, int w, int h) {
    m = malloc(sizeof(matrix));

    m->w = w;
    m->h = h;

    m->v = malloc(w * sizeof *(m->v));    
    for (int i = 0; i < w; i++) {
        m->v[i] = malloc(h * sizeof *(m->v[i]));
    }
}

On my main() function, I decided to give my new method a spin:

int main()
{
    matrix m;

    new_matrix(&m, 5, 5);

    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {
            m.v[i][j] = i*j;
        }
    }

    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {
            printf("%f", m.v[i][j]);
        }
    }
}

Now, you might have guessed it already from looking at the code (or not), but this crashes the moment I try to write something into the matrix, more specifically, on this line:

m.v[i][j] = i*j;

In my failed attempts at understanding the problem, I moved the first two nested for loops from main() to new_matrix(), and writing directly after malloc'ing. And that worked. So I guess the problem must be because the matrix is being malloc'ed in one function and changed in another??


回答1:


Your problem is here:

new_matrix(&m,

You already allocated space for a matrix on the stack, and passed the address of it to new_matrix.

Then new_matrix allocates a new one:

m = malloc(sizeof(matrix));

That new structure never escapes new_matrix.

Either have new_matrix return a pointer to matrix,

matrix * new_matrix(int w, int h) { ... }

Or have new_matrix operate on the m passed in.




回答2:


I think this line needs

m->v = malloc(w * sizeof *(m->v))

needs to be

m->v = malloc(w * sizeof *(mReal))

Because the array v is an array of mReal pointers

Then

m->v[i] = malloc(h * sizeof *(m->v[i]))

should be

m->v[i] = malloc(h * sizeof (mReal))

To hold the actual mReal value




回答3:


m->v = malloc(w * sizeof *(m->v));    
for (int i = 0; i < w; i++) {
    m->v[i] = malloc(h * sizeof *(m->v[i]));
}

The above few lines did this:

  1. allocate w count of sizeof(pointer to m->v) to m->v. pointers are integers by value so assume you're using 32bit integer you have 4w bytes allocated at m->v
  2. for each m->v location, allocate h count of sizeof(pointer to m->v[i]). this is another 4h bytes allocated, intentionally to m->v[i].

Now, I'm not sure where m->v[i] would be pointing right now... So a call to a random m.v[i][j] will most likely cause a seg fault.

I understand you want v to point to a w * h 2D array worth of memory space, so you should do

&v = (mReal *) malloc(w * h * sizeof(mReal));

instead of the block I quoted. You'll be able to traverse the memory block as 2D array. I did my experiment a while ago. 2D arrays are really consecutive memory blocks. C compiler will handle the address calculation at the back. So doing the above should solve your problem.

And yes, m = malloc(sizeof(matrix)); is redundant. This line will declare memory space of a matrix structure and assign it to m. As your m is passed in by reference, your initial matrix m; from main line has already done so.

@woolstar, constructor style function like matrix * new_matrix(int w, int h) {...} is not a good idea while working with pure C. Try run that on an old Diab C compiler...



来源:https://stackoverflow.com/questions/20412318/pointers-to-a-2d-array-and-manual-memory-management-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!