malloc

J

Joseph

I am trying to create a function that allocates memory for the matrix
through a function; like the code below. However, this does not seem to
work since I believe that the scope of the memory allocation only lasts
within the create function. Is there anyway around this? Thanx in
advance. I also DON'T want to declare int **matrix globally.


int main(void)
{
int **matrix;
create(matrix);
}

void create(int **matrix)
{ /*allocating mem for 2 by 3 int matrix*/
matrix = (int **)malloc(2*sizeof(int *));
matrix[0] = (int *)malloc(3*sizeof(int));
matrix[1] = (int *)malloc(3*sizeof(int));
}
 
C

Charles Harrison Caudill

Joseph said:
I am trying to create a function that allocates memory for the matrix
through a function; like the code below. However, this does not seem to
work since I believe that the scope of the memory allocation only lasts
within the create function. Is there anyway around this? Thanx in
advance. I also DON'T want to declare int **matrix globally.

int main(void)
{
int **matrix;
create(matrix);
}
void create(int **matrix)
{ /*allocating mem for 2 by 3 int matrix*/
matrix = (int **)malloc(2*sizeof(int *));
matrix[0] = (int *)malloc(3*sizeof(int));
matrix[1] = (int *)malloc(3*sizeof(int));
}

malloc allocates space on the heap. variable declarations in the
function allocate space on the stack. The stack goes away after
the function, the heap stays. That was too easy, and I'm bored,
so I'm going to rant...

Ok... time to have some fun...

(int *)malloc is redundant. The point of void * is that it matches
anything.

You could also statically allocate space on the stack inside your
main since the program dies when main does.

1) function pointers

int **create(int x, int y, void *(*malloc)(size_t)){
int i;
int **retval = (malloc)(sizeof(int) * x);
for(i = 0; i < y; i++)
retval = (malloc)(sizeof(int) * y);
return retval;
}

2) triple pointers

int main( void ){
int **matrix;
create(42, 42, &matrix);
}

void create(int x, int y, int ***target){
int i;
*target = malloc(sizeof(int) * x);
for(i = 0; i < y; i++)
(*target) = (malloc)(sizeof(int) * y);
}

ok, time to get back to compilers...
 
P

Pushkar Pradhan

I'm working on something similar, try the below,
they are 1-D matrices e.g. a 4X4 matrix will be accessed like this:
a[0], a[1], ... a[15].
If you want I have other functions like print_matrix also.
/*
** Generate a random matrix
*/
double * gen_matrix(int numRows, int numCols, int initialize)
{

double *x = NULL;
long i;

x = (double*)calloc( (numRows*numCols), sizeof(double) );
if(x == NULL) {
exit(-1);
}

/* initialize to zero */
if(!initialize) {
for(i = 0; i < numRows*numCols; i++) {
x = 0.0;
/*printf("%d %g\n", i, x);*/
}
}
else {
/* seed rand() with time so it starts randomly */
srand( (unsigned)time(NULL) );

for(i = 0; i < numRows*numCols; i++) {
x = i;
/*printf("%d %g\n", i, x);*/
}
}

return x;

}

int main(int argc, char **argv)
{

double *a = NULL;
double *b = NULL;
double *c = NULL;
/* other code */
a = gen_matrix(numRowsA, numColsA, 1);
b = gen_matrix(numRowsB, numColsB, 1);
c = gen_matrix(numRowsA, numColsB, 0);
....
free(a);
free(b);
free(c);

}
 
R

Robert Stankowic

Joseph said:
I am trying to create a function that allocates memory for the matrix
through a function; like the code below. However, this does not seem to
work since I believe that the scope of the memory allocation only lasts
within the create function. Is there anyway around this? Thanx in
advance. I also DON'T want to declare int **matrix globally.


int main(void)
{
int **matrix;
create(matrix);
}

void create(int **matrix)
{ /*allocating mem for 2 by 3 int matrix*/
matrix = (int **)malloc(2*sizeof(int *));
matrix[0] = (int *)malloc(3*sizeof(int));
matrix[1] = (int *)malloc(3*sizeof(int));
}

For sure not the best solution, but the experts here will point out what's
flawed :)

#include <stdlib.h>
#include <stdio.h>

#define NUM_ROWS 2
#define NUM_COLS 3

int **destroy(int **matrix, int rows)
{
int i;
for(i = 0; i < rows; i++)
{
free(matrix);
}
free(matrix);
matrix = NULL;
return matrix;
}

int ** create(int rows, int cols)
{
int **matrix;
int i;
int alloc_success = 1;

matrix = malloc(rows * sizeof *matrix);
if(matrix)
{
for(i = 0; i < rows; i++)
{
matrix = malloc(cols * sizeof **matrix);
if(!matrix)
{
alloc_success = 0;
}
}
if(!alloc_success)
{
matrix = destroy(matrix, rows);
}
}

return matrix;
}



int main(void)
{
int i;
int j;
int **matrix = create(NUM_ROWS, NUM_COLS);

/*use matrix*/
if(matrix)
{
for(i = 0; i < NUM_ROWS; i++)
{
for(j = 0; j < NUM_COLS; j++)
{
matrix[j] = i * NUM_COLS + j;
printf("%d\n", matrix[j]);
}
}
/*cleanup*/
destroy(matrix, NUM_ROWS);
return EXIT_SUCCESS;
}
return EXIT_FAILURE;
}

Robert
 
M

Martijn

Pushkar said:
I'm working on something similar, try the below,
they are 1-D matrices e.g. a 4X4 matrix will be accessed like this:
a[0], a[1], ... a[15].
If you want I have other functions like print_matrix also.
/*
** Generate a random matrix
*/
double * gen_matrix(int numRows, int numCols, int initialize)
{

double *x = NULL;
long i;

x = (double*)calloc( (numRows*numCols), sizeof(double) );
if(x == NULL) {
exit(-1);
}

why do you use calloc if you initialize it right after, anyway?
/* initialize to zero */
if(!initialize) {
for(i = 0; i < numRows*numCols; i++) {
x = 0.0;
/*printf("%d %g\n", i, x);*/
}
}
else {
/* seed rand() with time so it starts randomly */
srand( (unsigned)time(NULL) );

for(i = 0; i < numRows*numCols; i++) {
x = i;
/*printf("%d %g\n", i, x);*/
}
}

return x;

}


You could also have some fun and make a matrix type:

struct matrix
{
double* content;
unsigned int cols;
}

gen_matrix would be (I made it a litte more flexible, so it wouldn't exit on
failure):

struct matrix* gen_matrix(unsigned int rows, unsigned int cols)
{
struct matrix *matrix_ptr;

matrix_ptr = malloc(sizeof *matrix_ptr);
if ( matrix_ptr == NULL )
return ( NULL );

matrix_ptr->content = malloc(sizeof *matrix_ptr->content * rows *
cols);
if ( matrix_ptr->content == NULL )
{
free(matrix_ptr);
return ( NULL );
}

/* do any initialization of the content */

matrix_ptr->cols = cols;

return ( matrix_ptr );
}

Of course you could include the type it creates in both the name of the
structure and function (double vs int).

Now it is easier to use the indexes with getters and setters (uses 1-base
indexing, btw):

double get_matrix_value(struct matrix *matrix_ptr, unsigned int row,
unsigned int col)
{
if ( row == 0 || col == 0 )
return ( 0.0 ); /* set an error here */

return ( matrix_ptr->content[matrix_ptr->cols * (row - 1) + (col -
1)] );
}

Of course I don't check on out of bounds, so you would have to tweak this to
your needs (e.g. add the rows property to the structure as well, and check
for overflow).

Hope this helps,
 
M

Mike Wahler

Joseph said:
I am trying to create a function that allocates memory for the matrix
through a function; like the code below. However, this does not seem to >
work since I believe that the scope of the memory allocation only lasts >
within the create function. Is there anyway around this? Thanx in
advance. I also DON'T want to declare int **matrix globally.


int main(void)
{
int **matrix;
create(matrix);
}

void create(int **matrix)
{ /*allocating mem for 2 by 3 int matrix*/
matrix = (int **)malloc(2*sizeof(int *));
matrix[0] = (int *)malloc(3*sizeof(int));
matrix[1] = (int *)malloc(3*sizeof(int));
}

It's always a good idea to search past messages,
very likely your question has already been asked
and answered. From one of my recent posts (Sep 26):


#include <stdio.h>
#include <stdlib.h>

double **alloc2d(size_t rows, size_t cols)
{
double **result;
size_t row = 0;
size_t col = 0;

if(result = malloc(rows * sizeof *result))
{
if(*result = malloc(rows * cols * sizeof **result))
for(row = 1; row < rows; ++row)
result[row] = *result + row * cols;
else
{
free(result);
result = NULL;
}
}

return result;
}

void release2d(double **arr)
{
free(*arr);
free(arr);
}

void populate2d(double **arr, size_t rows, size_t cols)
{
size_t row = 0;
size_t col = 0;

for(row = 0; row < rows; ++row)
for(col = 0; col < cols; ++col)
arr[row][col] = row * cols + col;
}

void show2d(double **arr, size_t rows, size_t cols)
{
size_t row = 0;
size_t col = 0;

for(row = 0; row < rows; ++row)
{
for(col = 0; col < cols; ++col)
printf("%4.0f", arr[row][col]);

putchar('\n');
}
}

int main()
{
size_t rows = 10;
size_t cols = 10;
size_t row = 0;
size_t col = 0;
double **arr = NULL;
const int retcodes[] = {EXIT_FAILURE, EXIT_SUCCESS};
int status = 0;

if(status = (arr = alloc2d(rows, cols)) != NULL)
{
populate2d(arr, rows, cols);
show2d(arr, rows, cols);
release2d(arr);
}

printf("%s\n", status ? "" : "Cannot allocate memory");
return retcodes[status];
}

HTH,
-Mike
 
J

Joseph

I fail to understand why that the memory allocated in the void
create(int **matrix) does not remain. I passed the address of matrix so
shouldn't it still have the allocated memory when it returns to main.
The problem i am having is understanding why the printf statement in the
code below gives the value. I would have expected it to be 123 which is
the value I set it to in the create. Thanx in advance.

void create(int **matrix);

int main(void)
{
int **matrix;
create(matrix);

printf("%d", matrix[1][1]); /* ? */
}

void create(int **matrix)
{ /*allocating mem for 2 by 3 int matrix*/
matrix = (int **)malloc(2*sizeof(int *));
matrix[0] = (int *)malloc(3*sizeof(int));
matrix[1] = (int *)malloc(3*sizeof(int));

matrix[1][1] = 123;
}
 
B

Barry Schwarz

I am trying to create a function that allocates memory for the matrix
through a function; like the code below. However, this does not seem to
work since I believe that the scope of the memory allocation only lasts
within the create function. Is there anyway around this? Thanx in
advance. I also DON'T want to declare int **matrix globally.


int main(void)
{
int **matrix;
create(matrix);

Problems here:

matrix is uninitialized. Passing an uninitialized value to a
function (or any attempt to evaluate an uninitialized value) invokes
undefined behavior.

There is no way for the function to return the value/address of
the matrix it creates. Remember that c passes by value so that
whatever the function does to matrix actually happens to a copy of
matrix that is lost when the function returns.

There is no prototype in scope for create.

The solution to the prototype problem is obvious

There are two popular solutions to the other problems:

Since you only want to return one value, define the function to
do just that, as with the prototype
int** create(void);
Your function call the function with something like
matrix = create();
and the function would then look like
int** create(void){
int **ptr, i;
ptr = malloc(N * sizeof *ptr);
if (ptr == NULL){/* error handling */}
for (i = 0; i < M; i++){
ptr = malloc(N * sizeof *ptr);
if (ptr == NULL){/* error handling */}
}
return ptr;
}

If you really want the value returned in a variable, pass the
address of that variable to the function which can then dereference
the address and update the variable directly. The prototype would
look like
void create(int***);
The call would look like
create(&matrix);
and the function would look like
void create (int ***ptr){
int i;
*ptr = malloc(N * sizeof **ptr);
if ...
for (i = 0; i < M; i++){
(*ptr) = malloc(M * sizeof *(*ptr));
if ...
}
}
void create(int **matrix)
{ /*allocating mem for 2 by 3 int matrix*/
matrix = (int **)malloc(2*sizeof(int *));

While you are at it, NEVER cast the return from malloc. It can never
help but it can suppress compiler diagnostics you want to see.
matrix[0] = (int *)malloc(3*sizeof(int));
matrix[1] = (int *)malloc(3*sizeof(int));
}



<<Remove the del for email>>
 
R

Robert Stankowic

Joseph said:
I fail to understand why that the memory allocated in the void
create(int **matrix) does not remain. I passed the address of matrix so
shouldn't it still have the allocated memory when it returns to main.
The problem i am having is understanding why the printf statement in the
code below gives the value. I would have expected it to be 123 which is
the value I set it to in the create. Thanx in advance.

void create(int **matrix);

int main(void)
{
int **matrix;
create(matrix);

Here you pass a _copy_ of matrix. In create() you request (and hopefully
get, because you don't check the return value of malloc() for NULL) some
memory and assign the pointer malloc() returns to the _copy_ of matrix. This
_does not_ change the value of the original matrix in main(). So as soon as
you return from create() the requested memory is still there, but you lost
the pointer to it and therefore you have absolutely no way to access it.
there are two ways out:
1) look at my example I posted elsethread
2) pass a _pointer_ to matrix to create() like in

create(&matrix);

Now create gets the _address_ of the pointer and thus can modify the
**matrix in main()
(see below)
printf("%d", matrix[1][1]); /* ? */
}

void create(int **matrix)

This must be
void create(int ***ptr_to_matrix)
{ /*allocating mem for 2 by 3 int matrix*/
matrix = (int **)malloc(2*sizeof(int *));

*ptr_to_matrix = (int **)malloc(2*sizeof(int *));
or better
#include <stdlib.h> before your actual code and get rid of the cast and use
the preferred way of using the sizeof, which makes the statement remain
correct even if you change the type of **matrix:

*ptr_to_matrix = malloc(2 * sizeof **ptr_to_matrix);
......

(*ptr_to_matrix)[0] = malloc(3 * sizeof ***ptr_to_matrix);
matrix[0] = (int *)malloc(3*sizeof(int));
matrix[1] = (int *)malloc(3*sizeof(int));

matrix[1][1] = 123;
}

I personally _hate_ more than two levels of indirection, so I prefer to
return a pointer to the allocated memory and assign the returned pointr to
the original in the calling functions (see my example elsethread).

Please look at the examples given in our answers for better solutions and
proper error checking
HTH
Robert
 
A

Al Bowers

Joseph said:
I am trying to create a function that allocates memory for the matrix
through a function; like the code below. However, this does not seem to
work since I believe that the scope of the memory allocation only lasts
within the create function. Is there anyway around this? Thanx in
advance. I also DON'T want to declare int **matrix globally.


int main(void)
{
int **matrix;
create(matrix);
}

void create(int **matrix)
{ /*allocating mem for 2 by 3 int matrix*/
matrix = (int **)malloc(2*sizeof(int *));
matrix[0] = (int *)malloc(3*sizeof(int));
matrix[1] = (int *)malloc(3*sizeof(int));
}

The parameter matrix in function create is passed by value. A copy
is made and used in the function. It is changed with the malloc call.
But since it is a copy, matrix in function main remains unchanged.
To correct this and also add some safety and functionality make the
prototype:

int create(int ***matrix):

the definition and test code:

#include <stdlib.h>
#include <stdio.h>

int create(int ***matrix)
{
*matrix = malloc(2*(sizeof **matrix));
if(*matrix == NULL) return 0;
if(((*matrix)[0] = malloc(3*(sizeof ***matrix))) == NULL)
{
free(*matrix);
return 0;
}
if(((*matrix)[1] = malloc(3*(sizeof ***matrix))) == NULL)
{
free((*matrix)[0]);
free(*matrix);
return 0;
}
/* test */
(*matrix)[1][1] = 122;
return 1;
}

int main(void)
{
int **matrix;
if(create(&matrix))
printf("matrix[1][1] = %d\n",matrix[1][1]);
/* TODO Write code on free the dymanic allocations */
return 0;
}
 
C

cody

try that (not tested):

int main(void)
{
int **matrix;
create(matrix);
}

void create(int ***matrix)
{ /*allocating mem for 2 by 3 int matrix*/
*matrix = (int **)malloc(2*sizeof(int *));
(*matrix)[0] = (int*)malloc(3*sizeof(int));
(*matrix)[1] = (int*)malloc(3*sizeof(int));
}
 
D

Dan Pop

In said:
try that (not tested):

int main(void)
{
int **matrix;
create(matrix);

Undefined behaviour: you're implicitly declaring create() as function
returning int. You're also passing create() an uninitialised pointer of
the wrong type.
}

void create(int ***matrix)
{ /*allocating mem for 2 by 3 int matrix*/
*matrix = (int **)malloc(2*sizeof(int *));

Undefined behaviour: you're implicitly declaring malloc as a function
returning int. Due to the bogus cast, the compiler is not even required
to diagnose the bug.
(*matrix)[0] = (int*)malloc(3*sizeof(int));
(*matrix)[1] = (int*)malloc(3*sizeof(int));
}

Could you, please, consider learning C *before* continuing to post in this
newsgroup?

Dan
 
D

Dan Pop

In said:
ok iam so sorry, as i said my code was untested. at least i tried to help.

I can't see how such a thoroughly broken piece of code could help anyone.
First, learn C yourself and *only* then try to help other people. Tested
or not, your code clearly demonstrates your incompetence on C programming
issues.

Dan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top