UPDATE: I think I've answered my own question, except for some possible issues with memory leaks.
ORIGINAL QUESTION HERE, ANSWER BELOW.
Background: I'm doing some numerical computing, but I almost never use languages that require me to manage memory on my own. I'm piping something out to C now and am having trouble with (I think) pointer reference issues.
I have two arrays of doubles that are growing in a while loop, and at each iteration, I want to free the memory for the smaller, older array, set 'old' to point to the newer array, and then set 'new' to point to a larger block of memory.
After looking around a bit, it seemed as though I should be using pointers to pointers, so I've tried this, but am running into "lvalue required as unary ‘&’ operand" errors.
I start with:
double ** oldarray;
oldarray = &malloc(1*sizeof(double));
double ** newarray;
newarray = &malloc(2*sizeof(double));
These initializations give me an "lvalue required as unary ‘&’ operand" error, and I'm not sure whether I should replace it with
*oldarray = (double *) malloc(1*sizeof(double));
When I do that, I can compile a simple program (It just has the lines I have above and returns 0) but I get a seg fault.
The rest of the program is as follows:
while ( <some condition> ) {
// Do a lot of processing, most of which is updating
// the values in newarray using old array and other newarray values.
// Now I'm exiting the loop, and growing and reset ing arrays.
free(*oldarray) // I want to free the memory used by the smaller, older array.
*oldarray = *newarray // Then I want oldarray to point to the larger, newer array.
newarray = &malloc( <previous size + 1>*sizeof(double))
}
So I'd like to be, at each iteration, updating an array of size (n) using itself and an older array of size (n-1). Then I want to free up the memory of the array of size (n-1), set 'oldarray' to point to the array I just created, and then set 'newarray' to point to a new block of size (n+1) doubles.
Do I actually need to be using pointers to pointers? I think my main issue is that, when I set old to new, they share a pointee, and I then don't know how to set new to a new array. I think that using pointers to pointers gets me out of this, but, I'm not sure, and I still have the lvalue errors with pointers to pointers.
I've checked out C dynamically growing array and a few other stack questions, and have been googling pointers, malloc, and copying for about half a day.
Thanks!
HERE IS MY OWN ANSWER
I've now got a working solution. My only worry is that it might contain some memory leaks.
Using realloc() works, and I also need to be careful to make sure I'm only free()ing pointers that I initialized using malloc or realloc, and not pointers initialized with double * oldarray;.
The working version goes like this:
double * olddiagonal = (double *) malloc(sizeof(double));
olddiagonal[0] = otherfunction(otherstuff);
int iter = 1;
// A bunch of other stuff
while (<error tolerance condition>) {
double * new diagonal = (double *) malloc((iter+1)*sizeof(double));
newdiagonal[0] = otherfunction(moreotherstuff);
// Then I do a bunch of things and fill in the values of new diagonal using
// its other values and the values in olddiagonal.
// To finish, I free the old stuff, and use realloc to point old to new.
free(olddiagonal);
olddiagonal = (double *) realloc(newdiagonal, sizeof(double) * (iter+1));
iter++
}
This seems to work for my purposes. My only concern is possible memory leaks, but for now, it's behaving well and getting the correct values.
Here are some explanations:
double ** oldarray;
oldarray = &malloc(1*sizeof(double));
is wrong, because you don't store the result of malloc() anywhere, and since it is not stored anywhere, you can't take its address. You can get the effect that you seem to have had in mind by adding an intermediate variable:
double* intermediatePointer;
double** oldarray = &intermediatePointer;
intermediatePointer = malloc(1*sizeof(*intermediatePointer);
oldarray is now a pointer to the memory location of intermediatePointer, which points to the allocated memory slap in turn.
*oldarray = (double *) malloc(1*sizeof(double));
is wrong, because you are dereferencing an unitialized pointer. When you declare oldarray with double** oldarray;, you are only reserving memory for one pointer, not for anything the pointer is supposed to point to (the memory reservation is independent of what the pointer points to!). The value that you find in that pointer variable is undefined, so you have absolutely no control about what memory address you are writing to when you assign something to *oldarray.
Whenever you declare a pointer, you must initialize the pointer before you dereference it:
int* foo;
*foo = 7; //This is always a bug.
int bar;
int* baz = &bar; //Make sure the pointer points to something sensible.
*baz = 7; //OK.
Your answer code is indeed correct. However, it can be improved concerning style:
The combination of
int iter = 1;
while (<error tolerance condition>) {
...
iter++
}
calls for the use of the for() loop, which encapsulates the definition and incrementation of the loop variable into the loop control statement:
for(int iter = 1; <error tolerance condition>; iter++) {
...
}
In C, the cast of the return value of malloc() is entirely superfluous, it only clutters your code. (Note however that C++ does not allow the implicit conversion of void*s as C does, so int *foo = malloc(sizeof(*foo)) is perfectly valid C, but not legal in C++. However, in C++ you wouldn't be using malloc() in the first place.)
Related
I think I have a fundamental misunderstanding about memory and pointers in C. I'd like to ask why an array of pointers to structs needs malloc() called for individual elements of the array even though I'd think if they're getting initialized individually, then memory should be automatically allocated for them. Second, when filling up the array of pointers, it seems that it's necessary to copy the elements of the structs individually and simply copying the pointer to the struct itself doesn't work.
In other programs, I've been using structs and pointers a bit and I keep having to figure out the correct way to implement them, so I'd like to understand it intuitively rather than just taking for word "you just need to malloc() individual elements of the array"
/* suppose I have "typedef struct coord { int x; int y; } coord;" */
int num_rooms = 5;
coord* coordinates[num_rooms];
int i, j;
/* why is this required? in the following loop, coord[i] gets initialized,
and I thought memory automatically gets allocated on the stack because of
the initialization */
for (i = 0; i < num_rooms; i++) {
coordinates[i] = (coord*) malloc(sizeof(coord));
}
/* fill the array of coord pointers */
for (j = 0; j < num_rooms; j++) {
coord coordinate;
coord *coord_p;
coord_p = &coordinate;
coord_p->x = j;
coord_p->y = j;
/* this does not work. It just makes all array elements have the same struct elements. (the second question) Why does it require copying over individual field elements instead of copying the pointer?*/
//coordinates[j] = coord_p;
/* however, assigning individual elements doesn't cause segmentation fault */
coordinates[j]->x = coord_p->x;
coordinates[j]->y = coord_p->y;
}
If I uncomment coordinates[i] = coord_p; it ends up that all elements of the array have struct elements of the last initialized one. So if I printed every coordinate[i]->x and coordinate[i]->y it would saying '4 4' 5 times. But when I used the direct struct element copy, I get the correct output of '0 0, 1 1, 2 2, ...' if I printed it.
I expect that it should be fine to not allocate memory for individual elements of the array since they are initialized in a loop. I also expect that coordinates[i] = coord_p; should copy over the pointers value, letting something like printf("%d", coordinates[0]->x); work properly. However, in both cases I'm clearly misunderstanding something.
...why an array of pointers to structs needs malloc() called for individual elements of the array even though I'd think if they're getting initialized individually, then memory should be automatically allocated for them.
The simple answer is that C never allocates anything for you "automatically" in this sense.
One way to think about it is that C allocates just enough memory for your named variables, and that's it. If you say
int i;
C allocates enough memory for one int. If you say
double a[10];
C allocates enough memory for 10 doubles. If you say
int *p;
C allocates enough memory for one pointer-to-int, but it does not allocate any memory for that pointer to point to!
Almost without exception, when you declare pointers, it's your responsibility to think about the allocation of the memory that your pointers will point to. C never does that for you automatically.
In your specific example, when you said
coord* coordinates[5];
C allocated space for 5 pointers to coord -- but it allocated space for zero actual instances of coord. If, on the other hand, you had said
coord coordinatesa[5];
C would have allocated space for 5 actual instances of coord -- although you'd obviously use this array quite differently, since there are no pointers involved.
When you allocated 5 pointers, but no actual instances of coord, if you had tried to use one of the pointers, it would have been a serious error:
coord* coordinates[5];
coordinates[0]->x = 1; /* WRONG */
coordinates[0]->y = 2; /* WRONG */
One way to fix this would be to first make sure that coordinates[0] points somewhere:
coord* coordinates[5];
coordinates[0] = malloc(sizeof(coord));
coordinates[0]->x = 1; /* better */
coordinates[0]->y = 2; /* better */
Second, when filling up the array of pointers, it seems that it's necessary to copy the elements of the structs individually and simply copying the pointer to the struct itself doesn't work.
Ah, but when you copy pointers, you're carrying along the allocation of the source pointer, and losing the allocation of the destination pointer.
Taking my preceding example, and blending in part of your program, if you were to say
coord* coordinates[5];
coordinates[0] = malloc(sizeof(coord));
coord coordinate;
coord *coord_p;
coord_p = &coordinate;
coord_p->x = 1;
coord_p->y = 2;
coordinates[0] = coord_p;
This will "work", but it's wasteful and probably wrong. The memory allocated by the malloc call is never used, and when you say
coordinates[0] = coord_p;
the old pointer is overwritten and the pointed-to memory (that malloc so kindly gave you!) is lost.
After this assignment, the allocation of the memory pointed to by coordinates[0] is whatever coord_p's allocation was, which in this case is the single coord structure coordinate. As I say, this might seem to "work" at first, but if coordinate is a local variable that goes out of scope, or if you end up re-using it for all 5 coordinates in your coordinates array, you're going to have problems.
If, on the other hand, you say
*coordinates[0] = *coord_p;
or, equivalently,
coordinates[0]->x = coord_p->x;
coordinates[0]->y = coord_p->y;
now you're fetching data from the coord pointed to by coord_p, and safely copying it to the memory pointed to by coordinates[0]. Having done so, you've (a) properly used the memory you allocated for coordinates[0] to point to, and (b) insulated yourself from whatever happens later to the memory pointed to by coord_p.
But having gotten this far, in this case, we don't have to use the intermediate coord_p pointer at all. We could just as well say
coord coordinate;
coordinate.x = 1;
coordinate.y = 2;
*coordinates[0] = coordinate;
or, equivalently,
coordinates[0]->x = coordinate.x;
coordinates[0]->y = coordinate.y;
I'd like to ask why an array of pointers to structs needs malloc()
called for individual elements of the array even though I'd think if
they're getting initialized individually, then memory should be
automatically allocated for them.
It really isn't much different from having one pointer and allocating memory for it using malloc. Except instead of one pointer you have a whole array of pointers, so instead of just doing it once, you do it for each element of the array.
There's a problem with this part:
for (j = 0; j < num_rooms; j++) {
coord coordinate;
coord *coord_p;
coord_p = &coordinate;
coordinates[j] = coord_p;
}
coord coordinate is not dynamically allocated, so it's only valid until the end of the scope. At the end of the for loop, it becomes invalid. You save its pointer in coord_p and write that pointer to your array, but those pointers are all invalid afterwards.
But you already allocated memory for all the pointers, so you don't need to allocate any more. Just do this:
for (j = 0; j < num_rooms; j++) {
coordinates->x = j;
coordinates->y = j;
}
/* however, assigning individual elements doesn't cause segmentation fault */
coordinates[j]->x = coord_p->x;
coordinates[j]->y = coord_p->y;
The reason why this part works is that you're copying over the values of coord to your coordinates objects. Sure, coord becomes invalid at the end of the loop, but you made a copy of the values, which is fine.
I also expect that coordinates[i] = coord_p; should copy over the
pointers value, letting something like printf("%d", coordinates[0]->x); work properly. However, in both cases I'm clearly
misunderstanding something.
It copies the value of the pointer (not the object that is being pointed to, just the value of the pointer). The object that is pointed to isn't affected by that - it still has the same lifetime, which in this case is until the end of the loop. To actually copy the object being pointed to, do this:
*coordinates[i] = *coord_p;
This means "set the object pointed to by coordinates[i] to the object pointed to by coord_p".
I ran into a rather weird problem,
I have the following code:
typedef struct{
char *a;
char *b;
char *c;
}Str;
typedef struct{
int size;
str array[]; //flexible array.
}strArr;
The purpose here is to allocate a,b, and c for the new element from the realloc.
StrArr *arr;
int arrSize;
arrSize = 1;
arr = malloc(sizeof(strArr)+sizeof(int)*arrSize);
arr->size++;
arr = realloc(arr, sizeof(strArr)+sizeof(int)*arr->size);
arr->array[arr->size-1].a = malloc(sizeof(char)*75);
arr->size++;
card = realloc(arr, sizeof(strArr)+sizeof(int)*arr->size);
The question is: whenever arr is realloc'd to be one bigger, do you have to allocate memory for the strings of the new element? This code will fail if it is run because it gives me glibc detected at the second realloc. What am I doing wrong? If i take off the malloc statement in the middle it runs. Also, if i try a strcpy into arr->array[arr->size-1].a, it would segfault.
Any help would be appreciated.
Thank you.
There are numerous issues with this code, enough to suggest that whatever you're experiencing can't be reproduced. Nonetheless, there are sufficient problems to cause instability (i.e. segmentation violations). I'm going to assume you meant to use a lowercase s in str rather than an uppercase S in Str; it only makes sense that way. Similarly for the lowercase s (which should be) in strArray.
At which point have you assigned arr->size a value in order for arr->size++; to be useful? That itself is a mistake, but that's interlaced into another mistake:
arr = realloc(arr, sizeof(strArr)+sizeof(int)*arr->size);
That turns out to be a major issue as you continue to use the uninitialised variable in critical pieces of logic, again and again, nonetheless, once that issue is resolved, the next mistake here is:
Anything that resembles the pattern X = realloc(X, Y); is suspicious. It's the Xes. Those should be different. You're not supposed to just replace the values like that. I mean, it'll work, kind of... but it's not much more effort to do it properly, and unless done properly, this won't be valgrind-friendly. That should be a big deal to you, because valgrind is a tool that helps us identify memory leaks!
You should store this into a temporary variable:
void *temp = realloc(X, Y);
... and then you can handle errors, perhaps by cleaning up and exiting properly:
if (temp == NULL) {
perror("realloc");
/* free(X); // what would valgrind cease complaining about? */
exit(EXIT_FAILURE);
}
... and replacing X with temp:
X = temp;
sizeof(int) should not be assumed to be the same size as sizeof str (whatever str is). Given the type of arr->array, I would expect sizeof str or, better yet, here's a nice pattern to keep in mind:
// X = realloc(Y, Z); or ...
void *temp = realloc(arr, sizeof *arr + arr->size * sizeof arr->array[0]);
// XXX: handle errors
The question is: whenever arr is realloc'd to be one bigger, do you have to allocate memory for the strings of the new element?
The strings themselves should be in a separate storage location to the list nodes. What is this? Strings and list nodes, in the same array?!
I suppose it might make sense if by strings you mean fixed-width, null padded fields. Fixing the width of the field makes expressing the array in a one-dimensional space much easier.
Otherwise, you should keep your strings allocated separately from your list nodes... in a manner with which the down-stream programmer has complete control over, if I may add, is kinda nice, though you lose that the moment you use realloc, malloc, etc (and thus the moment you use VLAs, hmmmm!)...
What am I doing wrong?
I think I've picked apart your code sufficing to say:
Initialise all of your variables before you use them. In this case, there are some variables pointed at by arr which are used without first being initialised.
Don't assume sizeof(int) and sizeof (/*any pointer type*/) have the same width. There are very real systems where this won't be true.
Remember to use that X = realloc(Y, Z); pattern, followed by error handling, followed by Y = X;.
I'm still not sure whether forcing down-stream programmers to rely upon malloc/realloc/etc and free is necessary, or even beneficial, here.
Also, if i try a strcpy into arr->array[arr->size-1].a, it would segfault.
Yes, well... there's that phantom arr->size-related issue again!
I have two pointers, each pointing to a different array. One of the pointers is inside of a struct, as follows:
typedef struct
{
int N; /* Number of Elements in array */
double *c; /* Pointer to an array */
/* Other members.... */
} CS;
The struct was initialized by:
CS->N = n; /* n is an integer of an initially unknown size */
CS->c = (double *)malloc(n * sizeof(double));
The pointer in the struct, CS->C, contains data that I no longer care about.
My other pointer was defined as follows:
double *alpha;
alpha = (double *)malloc(CS->N * sizeof(double));
I need to replace the contents of CS->C with alpha. I know I can do something naive like:
for (i=0;i<CS->N;i++) /* i is an integer */
CS->c[i] = alpha[i];
I could also use memcpy, like this:
memcpy(CS->c,alpha,CS->N * sizeof(double));
My understanding is that both of these methods will copy the contents from memory located at alpha to the memory occupied by CS->C. That being a very expensive operation, it would make more sense to simply change the assignment of CS->C to alpha.
How can I do this?
I've tried to reassign the pointer by doing like CS->C = &alpha, but this gives me the following warning "assignment from incompatible pointer type".
Note: This is using ANSI C89 under full compliance, i.e. the compiler options are: -Wall -pedantic -ansi
Edit 1
Freeing CS->c and assigning it to alpha by doing:
free(CS->c);
CS->c = alpha;
does not work. It causes every entry in CS->c to become equal to 0.0 and it results in my program seg faulting.
Edit 2
I think I realized why the method suggested in my first edit did not work. alpha is a temporary pointer, created and initialized inside of a function, so once that function is exited, the memory occupied by alpha is "freed". Since CS->c points to that memory, it is also freed. Upon this discovery, I think I will rework my code, such that alpha and CS-c are initially swapped, such that when they are switched again, the end order will be correct. Thank you all for you valuable input.
Just copy the pointer
CS->C = alpha;
Alpha is a pointer to double, CS->C too, types matches, you simply change the pointer.
/!\ Don't forgot to free the old CS->C ...
Free the old pointer and assing the new directly. (Not the adress of the new pointer)
The pointer in the struct, CS->c, contains data that I no longer
care about.
My other pointer was defined as follows:
double *alpha;
alpha = malloc(CS->N * sizeof(double));
...
free (CS->c);
CS->c = alpha ; alpha=NULL;
I'm new to C and haven't really grasped when C decides to free an object and when it decides to keep an object.
heap_t is pointer to a struct heap.
heap_t create_heap(){
heap_t h_t = (heap_t)malloc(sizeof(heap));
h_t->it = 0;
h_t->len = 10;
h_t->arr = (token_t)calloc(10, sizeof(token));
//call below a couple of times to fill up arr
app_heap(h_t, ENUM, "enum", 1);
return h_t;
}
putting h_t through
int app_heap(heap_t h, enum symbol s, char* word, int line){
int it = h->it;
int len = h->len;
if (it + 1 < len ){
token temp;
h->arr[it] = temp;
h->arr[it].sym = s;
h->arr[it].word = word;
h->arr[it].line = line;
h->it = it + 1;
printf(h->arr[it].word);
return 1;
} else {
h->len = len*2;
h->arr = realloc(h->arr, len*2);
return app_heap(h, s, word, line);
}
}
Why does my h_t->arr fill up with junk and eventually I get a segmentation fault? How do I fix this? Any C coding tips/styles to avoid stuff like this?
First, to answer your question about the crash, I think the reason you are getting segmentation fault is that you fail to multiply len by sizeof(token) in the call to realloc. You end up writing past the end of the block that has been allocated, eventually triggering a segfault.
As far as "deciding to free an object and when [...] to keep an object" goes, C does not decide any of it for you: it simply does it when you tell it to by calling free, without asking you any further questions. This "obedience" ends up costing you sometimes, because you can accidentally free something you still need. It is a good idea to NULL out the pointer, to improve your chance of catching the issue faster (unfortunately, this is not enough to eliminate the problem altogether, because of shared pointers).
free(h->arr);
h -> arr = NULL; // Doing this is a good practice
To summarize, managing memory in C is a tedious task that requires a lot of thinking and discipline. You need to check the result of every allocation call to see if it has failed, and perform many auxiliary tasks when it does.
C does not "decide" anything, if you have allocated something yourself with an explicit call to e.g. malloc(), it will stay allocated until you free() it (or until the program terminates, typically).
I think this:
token temp;
h->arr[it] = temp;
h->arr[it].sym = s;
/* more accesses */
is very weird, the first two lines don't do anything sensible.
As pointed out by dasblinkenlight, you're failing to scale the re-allocation into bytes, which will cause dramatic shrinkage of the array when it tries to grow, and corrupt it totally.
You shouldn't cast the return values of malloc() and realloc(), in C.
Remember that realloc() might fail, in which case you will lose your pointer if you overwrite it like you do.
Lots of repetition in your code, i.e. realloc(h->arr, len*2) instead of realloc(h->arr, h->len * sizeof *h->arr) and so on.
Note how the last bullet point also fixes the realloc() scaling bug mentioned above.
You're not reallocating to the proper size, the realloc statement needs to be:
realloc(h->arr, sizeof(token) * len*2);
^^^^^^^^^^^^
(Or perhaps better realloc(h->arr, sizeof *h->arr * h->h_len);)
In C, you are responsible to free the memory you allocate. You have to free() the memory you've malloc/calloc/realloc'ed when it's suitable to do so. The C runtime never frees anything, except when the program has terminated(some more esoteric systems might not release the memory even then).
Also, try to be consistent, the general form for allocating is always T *foo = malloc(sizeof *foo), and dont duplicate stuff.
e.g.
h_t->arr = (token_t)calloc(10, sizeof(token));
^^^^^^^^ ^^ ^^^^^^^^^^^^^
Don't cast the return value of malloc in C. It's unncessesary and might hide a serious compiler warning and bug if you forget to include stdlib.h
the cast is token_t but the sizeof applies to token, why are they different, and are they the same type as *h_t->arr ?
You already have the magic 10 value, use h_t->len
If you ever change the type of h_t->arr, you have to remember to change the sizeof(..)
So make this
h_t->arr = calloc(h_t->len, sizeof *h_t->arr);
Two main problems in creating dangling pointers in C are the not assigning
NULL to a pointer after freeing its allocated memory, and shared pointers.
There is a solution to the first problem, of automatically nulling out the pointer.
void SaferFree(void *AFree[])
{
free(AFree[0]);
AFree[0] = NULL;
}
The caller, instead calling
free(p);
will call
SaferFree(&p);
In respect to the second and harder to be siolved issue:
The rule of three says:
If you need to explicitly declare either the destructor, copy constructor or copy assignment operator yourself, you probably need to explicitly declare all three of them.
Sharing a pointer in C is simply copying it (copy assignment). It means that using the rule of three (or the general rule of 0)
when programming in C obliges the programmer to supply a way to construct and especially destruct such an assignment, which is possible, but not an
easy task especially when C does not supply a descructor that is implicitly activated as in C++.
I have written a some C code running on OS X 10.6, which happens to be slow so I am using valgrind to check for memory leaks etc. One of the things I have noticed whilst doing this:
If I allocate memory to a 2D array like this:
double** matrix = NULL;
allocate2D(matrix, 2, 2);
void allocate2D(double** matrix, int nrows, int ncols) {
matrix = (double**)malloc(nrows*sizeof(double*));
int i;
for(i=0;i<nrows;i++) {
matrix[i] = (double*)malloc(ncols*sizeof(double));
}
}
Then check the memory address of matrix it is 0x0.
However if I do
double** matrix = allocate2D(2,2);
double** allocate2D(int nrows, int ncols) {
double** matrix = (double**)malloc(nrows*sizeof(double*));
int i;
for(i=0;i<nrows;i++) {
matrix[i] = (double*)malloc(ncols*sizeof(double));
}
return matrix;
}
This works fine, i.e. the pointer to the newly created memory is returned.
When I also have a free2D function to free up the memory. It doesn't seem to free properly. I.e. the pointer still point to same address as before call to free, not 0x0 (which I thought might be default).
void free2D(double** matrix, int nrows) {
int i;
for(i=0;i<nrows;i++) {
free(matrix[i]);
}
free(matrix);
}
My question is: Am I misunderstanding how malloc/free work? Otherwise can someone suggest whats going on?
Alex
When you free a pointer, the value of the pointer does not change, you will have to explicitly set it to 0 if you want it to be null.
In the first example, you've only stored the pointer returned by malloc in a local variable. It's lost when the function returns.
Usual practice in the C language is to use the function's return value to pass the pointer to an allocated object back to the caller. As Armen pointed out, you can also pass a pointer to where the function should store its output:
void Allocate2D(double*** pMatrix...)
{
*pMatrix = malloc(...)
}
but I think most people would scream as soon as they see ***.
You might also consider that arrays of pointers are not an efficient implementation of matrices. Allocating each row separately contributes to memory fragmentation, malloc overhead (because each allocation involves some bookkeeping, not to mention the extra pointers you have to store), and cache misses. And each access to an element of the matrix involves 2 pointer dereferences rather than just one, which can introduce stalls. Finally, you have a lot more work to do allocating the matrix, since you have to check for failure of each malloc and cleanup everything you've already done if any of them fail.
A better approach is to use a one-dimensional array:
double *matrix;
matrix = malloc(nrows*ncols*sizeof *matrix);
then access element (i,j) as matrix[i*ncols+j]. The potential disadvantages are the multiplication (which is slow on ancient cpus but fast on modern ones) and the syntax.
A still-better approach is not to seek excess generality. Most matrix code on SO is not for advanced numerical mathematics where arbitrary matrix sizes might be needed, but for 3d gaming where 2x2, 3x3, and 4x4 are the only matrix sizes of any practical use. If that's the case, try something like
double (*matrix)[4] = malloc(4*sizeof *matrix);
and then you can access element (i,j) as matrix[i][j] with a single dereference and an extremely fast multiply-by-constant. And if your matrix is only needed at local scope or inside a structure, just declare it as:
double matrix[4][4];
If you're not extremely adept with the C type system and the declarations above, it might be best to just wrap all your matrices in structs anyway:
struct matrix4x4 {
double x[4][4];
};
Then declarations, pointer casts, allocations, etc. become a lot more familiar. The only disadvantage is that you need to do something like matrix.x[i][j] or matrix->x[i][j] (depending on whether matrix is a struct of pointer to struct) instead of matrix[i][j].
Edit: I did think of one useful property of implementing your matrices as arrays of row pointers - it makes permutation of rows a trivial operation. If your algorithms need to perform a lot of row permutation, this may be beneficial. Note that the benefit will not be much for small matrices, though, and than column permutation cannot be optimized this way.
In C++ You should pass the pointer by reference :)
Allocate2D(double**& matrix...)
As to what's going on - well you have a pointer that is NULL, you pass the copy of that pointer to the function which allocated mamory and initializes the copy of your pointer with the address of the newly allocated memory, but your original pointer remains NULL. As for free you don't need to pass by reference since only the value of the pointer is relevant. HTH
Since there are no references in C, you can pass by pointer, that is
Allocate2D(double*** pMatrix...)
{
*pMatrix = malloc(...)
}
and later call like
Allocate2D(&matrix ...)