Dynamic memory allocation question (in C)
Consider following codes:
#include <stdio.h>
#include <malloc.h>
void allocateMatrix(int **m, int l, int c)
{
int i;
m = (int**) malloc( sizeof(int*) * l );
for(i = 0; i < l; i++)
m[i] = (int*) malloc( sizeof(int) * c );
}
int main()
{
int **m;
int l = 10, c = 10;
allocateMatrix(m, l, c);
m[0][0] = 9;
printf("%d", m[0][0]);
return 0;
}
The code above will generate an memory allocation error and will crash.
But the code below will work correctly, the question is: WHY?
#include <stdio.h>
#include <malloc.h>
int** allocateMatrix(int l, int c)
{
int i;
开发者_JAVA百科int **m = (int**) malloc( sizeof(int*) * l );
for(i = 0; i < l; i++)
m[i] = (int*) malloc( sizeof(int) * c );
return m;
}
int main()
{
int **m;
int l = 10, c = 10;
m = allocateMatrix(l, c);
m[0][0] = 9;
printf("%d", m[0][0]);
return 0;
}
I cannot see why the first code crashes, since I'm just passing the pointer-to-pointer m (the variable that holds the memory first memory address of the matrix) as an argument. I see no difference between the codes (in practice). I would appreciate any clear explanation.
Thank you, Rafael Andreatta
In the first example you don't initialize m. You merely change your copy of it. So, put otherwise, the caller will never see what you did to m
.
In the second example you allocate memory and then return a pointer to it. Which is valid.
You might be able to fix your first example like this (untested but should work):
void allocateMatrix(int ***m, int l, int c)
{
int i;
*m = malloc( sizeof(int*) * l );
for(i = 0; i < l; i++)
(*m)[i] = malloc( sizeof(int) * c );
}
/* ... */
allocateMatrix(&m, l, c);
EDIT
Took me a while but I found it. As usual the C FAQ has something to say about this.
The function allocateMatrix receives a copy of the passed variable m, not the variable the you are passing from the main. Thus, in the first example m is not initialized and when you try to access is you get a segmentation fault.
This is a tricky one, and happens because with:
void allocateMatrix(int **m, int l, int c);
you're one level of indirection out. If you pass a pointer, the value that points to is in effect passed by reference. However, the actual pointer value is copied onto the stack, i.e. is still pass by value. So your allocation function has a local copy of the heap address, but this is never re-assigned to m
in the preceding scope.
To fix this, you can use either the second case, or this:
void allocateMatrix(int ***m, int l, int c)
{
int i;
*m = (int**) malloc( sizeof(int*) * l );
for(i = 0; i < l; i++)
(*m)[i] = (int*) malloc( sizeof(int) * c );
}
and pass with &m
.
I also would like to point out in C, you probably are better off not casting the result of malloc, although you are required to in C++. See this answer.
Because in first example variable m (in main) is not changed. To change it, you must pass it as reference (in C++) or by pointer (in plain C).
精彩评论