releasing dynamic memory of pointer of pointers in C - c

I have an error while trying to release memory of dynamic array.
void Ex()
{
int **Matrix = dyn_matrix_allocation(rows, cols);
.
.
.
free_My_Dyn_Mem(Matrix, rows);
}
void free_My_Dyn_Mem(int **to_Release, int size)
{
int i;
for (i = 0; i < size; i++)
free(to_Release[i]);
//free(to_Release); - If I do this, the program crash.
}
void **dyn_matrix_allocation(int rows, int cols)
{
void **matrix = (void**)calloc (sizeof(int*), cols);
assert(matrix); /*calloc worked*/
int i;
for (i = 0; i < rows; i++)
{
matrix[i] = (int*)calloc(sizeof(int), rows);
assert(matrix[i]); /*calloc worked*/
}
return matrix;
}
after releasing the array itself, I'm trying to release the pointer of pointers (**matrix) then I get an error. debugger shows nothing special. any ideas why?

You made a couple of errors in allocating your dynamic matrix due to unclear definition of your 2D addressing.
First error in allocation, here you choose to create your matrix column dependent allocating an array of cols pointers ti int:
void **matrix = (void**)calloc (sizeof(int*), cols);
Now you should allocate an array of rows integers per each column, but you assign rows arrays of integers:
for (i = 0; i < rows; i++) //Should be for (i = 0; i < cols; i++)
{
matrix[i] = (int*)calloc(sizeof(int), rows);
assert(matrix[i]); /*calloc worked*/
}
Up to now some compilers, or lint or even good debuggers should have told you that you where outside bounds.
But the exception triggers when you free the memory still using the wrong addressing.
void Ex()
{
int **Matrix = dyn_matrix_allocation(rows, cols);
.
.
.
free_My_Dyn_Mem(Matrix, rows); //But you allocated cols pointers...
}
You should pass the array of integer pointers that has a size of cols members, not rows.
Now you release what you allocated out of bounds:
for (i = 0; i < size; i++)
free(to_Release[i]);
The debugger should have complained a lot!
Then you release a now corrupted memory...
free(to_Release);
Your code should be:
#include <stdlib.h>
#include <assert.h>
void free_My_Dyn_Mem(int **to_Release, int size)
{
int i;
for (i = 0; i < size; i++)
free(to_Release[i]);
free(to_Release); //- If I do this, the program crash.
}
int **dyn_matrix_allocation(int rows, int cols)
{
int **matrix = calloc(sizeof(int *), cols);
assert(matrix); /*calloc worked */
int i;
//for (i = 0; i < rows; i++)
for (i = 0; i < cols; i++)
{
matrix[i] = calloc(sizeof(int), rows);
assert(matrix[i]); /*calloc worked */
}
return matrix;
}
void Ex(void)
{
int rows = 100;
int cols = 20;
int **Matrix = dyn_matrix_allocation(rows, cols);
//.
//.
//.
//free_My_Dyn_Mem(Matrix, rows);
free_My_Dyn_Mem(Matrix, cols);
}
Remember that you chosen a columns ordered matrix.
P.S. I forget to add that asserts are normally used for development checks and they can be removed defining the symbol NDEBUG. When you need a permanent control, like an error on allocation return, you should use standard if (condition) ErrorHandling(...);.

Related

Process a 2D array made with different methods in the same function in C

I have created two matrices in C with the following code:
static allocation method
int data[NMAX][NMAX]; // define NMAX 10 is in header
dynamic allocation method
int** data = (int**) malloc(sizeof(int*) * N);
for (int i = 0; i < N; i++) {
data[i] = (int*) malloc(sizeof(int) * M);
}
now i want to insert data into them with ONE function like so:
int inputMatrix(int **data, int N, int M) { ... }
How can i make the same function declaration work for both array types?
Currently it outputs
expected 'int **' but argument is of type 'int ** (*)[10]'
I have tried creating the static array like this:
int* data[NMAX];
for (int i = 0; i < N; i++) {
data[i] = (int[NMAX]) {};
}
but this code produces a matrix with every line being the same after I input numbers into it
The function inputMatrix will take an array whose elements are pointers to int, so you can create an array that holds pointers to each rows of statically allocated array and pass that to the function.
Construction of the pointer array can be done like this:
int data[NMAX][NMAX];
int *pdata[NMAX]; // array of pointers
for (int i = 0; i < N; i++) {
pdata[i] = data[i]; // the array data[i] is converted to pointers to their first elements here
}
##EDI##
You array pointers
int arr[10][5];
int main(void)
{
srand(time(NULL));
fillArray(5, 10, arr);
printArray(5, 10, arr);
}
See the implementations below https://godbolt.org/z/M6GhrEojn
Do not use arrays of pointers. Use array pointers instead. You remove one level of indirection and you can allocate and free it using one function call. As the whole array is a contignous chunk of memory it is much easier for processor yo use the cache.
void *allocateArray(size_t rows, size_t cols)
{
int (*a)[cols] = malloc(rows * sizeof(*a));
return a;
}
and example usage:
void fillArray(size_t cols, size_t rows, int (*arr)[cols])
{
for(size_t row = 0; row < rows; row++)
for(size_t col = 0; col < cols; col++)
arr[row][col] = rand();
}
void printArray(size_t cols, size_t rows, int (*arr)[cols])
{
for(size_t row = 0; row < rows; row++)
{
for(size_t col = 0; col < cols; col++)
printf("[%02zu][%02zu]%d,\t", row, col, arr[row][col]);
printf("\n");
}
}
int main(void)
{
size_t cols, rows;
scanf("%zu,%zu", &rows, &cols);
printf("rows:%zu, cols:%zu", rows, cols);
int (*array)[cols] = allocateArray(rows, cols);
srand(time(NULL));
printf("%p\n", array);
if(array)
{
fillArray(rows, cols, array);
printArray(rows, cols, array);
}
free(array);
}

Using pointers and malloc alone, how to define 2D int array? mine seems doesnt work. (seg fault)

I want to declare 2D-array in .h file without given numbers of COLS nor ROWS (cause they are read somewhere from inside the main() )
I mean I could tried another way of doing this like below
if one of ROWS and COLS is given at the firsthand.
int COLS = 20;
int (*array)[COLS];
array = malloc((*array) * ROWS);
thus I tried like below:
below is 2d.h
int* a;
int** b;
int size;
below is test2d.c, inside int main(){}
read_size() //size value read from some file
a = malloc(sizeof(int) * size);
b = malloc(sizeof(*a) * size);
for(int i=0; i<size; i++){
for(int j=0; j<size; j++){
b[i][j] = i+j;
printf("ok");
}
}
//print all
should be printing all 0112 but the result is segmentation fault.
To allocate a 2D array you need to allocate the 2D pointer b, which you have done. After that you need to allocate memory for b[i] in a for loop as below
// cols and rows are input by user or other parts of program.
int **b;
b = malloc(sizeof(int*) * rows);
for(int i=0; i<rows; i++){
b[i] = malloc(sizeof(int) * cols);
}
The explanation for this is that b is an array of pointers to int. In each element of b you allocate an array of int. This gives you a 2D array.
If you want a rectangular (not jagged array), it's most efficient to allocate all the cells as a single block, then the row pointers can all point into that block:
#include <stdlib.h>
int **make_array(size_t height, size_t width)
{
/* assume this multiplication won't overflow size_t */
int *cells = malloc((sizeof *cells) * height * width);
int **rows = malloc((sizeof *rows) * height);
if (!rows || !cells) {
free(cells);
free(rows);
return 0;
}
/* now populate the array of pointers to rows */
for (size_t row = 0; row < height; ++row) {
rows[row] = cells + width * row;
}
return rows;
}
This also makes deallocation much simpler, as we no longer need a loop:
void free_array(int **a)
{
if (!a) return;
free(a[0]);
free(a);
}

Scanf Segfaults Outside of main()

I'm trying to generate a matrix of some arbitrary dimensions. I can do it just fine by calling scanf in main and then assigning matrix elements on a row by row basis, but trying to do it in a single function, outside of main, (and only if scanf() is called outside of main) gives me a segfault error:
int **genmat(int nrow, int ncol){
int i,j;
int **mat = (int**) malloc(sizeof(int)*ncol*nrow);
char rowbuff[16];
for(i=0; i < nrow; i++){
INPUT: scanf("%[^\n]%*c",rowbuff);
if(strlen(rowbuff) != ncol){
printf("Error: Input must be string of length %d\n", ncol);
goto INPUT;
}
else{
for(j=0; j < ncol; j++){
if(rowbuff[j] == '1'){
mat[i][j] = 1;
}
else{
mat[i][j] = 0;
}
}
}
}
return(mat);
}
The following works just fine:
int *genrow(int ncol, char *rowbuff){
int i;
int *row = malloc(sizeof(int)*ncol);
for(i=0;i<ncol;i++){
row[i] = rowbuff[i]%2;
}
return(row);
}
with the following in my main function to call genrow() for each row of the matrix:
for(i=0; i < row; i++){
INPUT: scanf("%[^\n]%*c",rowbuff);
if(strlen(rowbuff) != col){
printf("Error: Input must be string of length %d\n", col);
goto INPUT;
}
else{
int *newrow = genrow(col, rowbuff);
for(j=0; j < col; j++){
matrix[i][j] = newrow[j];
}
free(newrow);
newrow = NULL;
}
}
Why is the behavior different in these two contexts?
Dynamically allocated 2D arrays are unfortunately burdensome and ugly in C. To properly allocate one, it is very important that you do so with a single call to malloc, just as you tried to do. Otherwise it won't be a 2D array, but instead some segmented, slow look-up table.
However, the result of that malloc call will be a pointer to a 2D array, not a pointer-to-pointer. In fact, pointer-pointers have nothing to do with 2D arrays whatsoever - this is a widespread but incorrect belief.
What you should have done is this:
int (*mat)[nrow][ncol] = malloc( sizeof(int[nrow][ncol] );
This is an array pointer to a 2D array. This syntax is already a bit burdensome, but to make things worse, it is not easy to pass this array pointer back to main, because it is a local pointer variable. So you would need to use a pointer to an array pointer... and there's no pretty way to do that. It goes like this:
void genmat (size_t nrow, size_t ncol, int (**mat)[nrow][ncol] )
{
*mat = malloc( sizeof(int[nrow][ncol]) );
To ease usage a bit, you can create a temporary pointer to rows, which doesn't require multiple levels of indirection and is therefore much easier to work with:
int (*matrix)[ncol] = *mat[0]; // in the pointed-at 2D array, point at first row
for(size_t r=0; r<nrow; r++) // whatever you want to do with this matrix:
{
for(size_t c=0; c<ncol; c++)
{
matrix[r][c] = 1; // much more convenient syntax than (**mat)[r][c]
}
}
From main, you'll have to call the code like this:
size_t row = 3;
size_t col = 4;
int (*mat)[row][col];
genmat(row, col, &mat);
Example:
#include <stdio.h>
#include <stdlib.h>
void genmat (size_t nrow, size_t ncol, int (**mat)[nrow][ncol] )
{
*mat = malloc( sizeof(int[nrow][ncol]) );
int (*matrix)[ncol] = *mat[0];
for(size_t r=0; r<nrow; r++)
{
for(size_t c=0; c<ncol; c++)
{
matrix[r][c] = 1;
}
}
}
void printmat (size_t nrow, size_t ncol, int mat[nrow][ncol])
{
for(size_t r=0; r<nrow; r++)
{
for(size_t c=0; c<ncol; c++)
{
printf("%d ", mat[r][c]);
}
printf("\n");
}
}
int main (void)
{
size_t row = 3;
size_t col = 4;
int (*mat)[row][col];
genmat(row, col, &mat);
printmat(row, col, *mat);
free(mat);
return 0;
}
Please note that real code needs to address the case where malloc returns NULL.
I assume the problems is withint **mat = (int**) malloc(sizeof(int)*ncol*nrow);
You are trying to allocate the a 2D array right? But this isn't the correct method to allocate the memory. You can't allocate the whole chunk of memory one short.
What you should be doing here is, allocate the memory for all the rows(basically pointer to store the column address) and then for columns
int **mat= (int **)malloc(nrow * sizeof(int *));
for (i=0; i<nrow; i++)
mat[i] = (int *)malloc(ncol * sizeof(int));
Refer this link for more info http://www.geeksforgeeks.org/dynamically-allocate-2d-array-c/

Difference between applying free() on **my_vector and ***my_vector

I found a function that frees memory of a matrix:
void free_matrix(int ***matrix, int rows, int cols) {
int row;
if (matrix != NULL && *matrix != NULL) {
for (row = 0; row < rows; row++) {
free((*matrix)[row]);
(*matrix)[row] = NULL;
}
free(*matrix);
*matrix = NULL;
}
}
I call the method like this:
int **my_vector = create_matrix(5, 5);
free_matrix(&my_vector, 5, 5);
I don't quite understand why the author decided to use ***matrix and not **matrix since in my other method where I create the matrix, he is exactly doing that:
void fill_matrix(int **matrix, int rows, int cols) {
int row = 0;
int col = 0;
for (row = 0; row < rows; row++) {
for (col = 0; col < cols; col++) {
matrix[row][col] = ((row + 1) * 10) + col;
}
}
}
int **create_matrix(int rows, int cols) {
int row;
int **matrix = malloc(rows * sizeof(int *));
for (row = 0; row < rows; row++) {
matrix[row] = malloc(cols * sizeof(int));
}
return matrix;
}
There must a reason why suddenly the author decided to use int ***matrix instead of int **matrix.
The author passes the address of the matrix pointer to allow the free_matrix matrix to reset the pointer to NULL in the caller's scope. It is a precaution to prevent accesses to the matrix data after it has been freed, but if the caller made a copy of the matrix pointer, it can still invoke undefined behavior by accessing it via the copy.
As suggested by Olaf, matrices should be implemented as 2D arrays, for much simpler allocation and deallocation:
/* allocating a pointer to a 2D array matrix[rows][cols] filled to 0 */
int (*matrix)[cols] = calloc(sizeof(*matrix), rows);
/* free the matrix */
free(matrix); matrix = NULL;
But, if the sizes are not constant, the syntax required to pass these matrices as function arguments or worse to return them is not so obvious and requires a C99 compliant compiler.
To clarify the dubious advantage of the *** approach, lets look at the more common 2 star solution:
void free_matrix(int **matrix, int rows, int cols) {
int row;
if (matrix != NULL) {
for (row = 0; row < rows; row++) {
free(matrix[row]);
}
free(matrix);
}
}
int main(void) {
int **my_vector = create_matrix(5, 5);
fill_matrix(my_vector, 5, 5);
free_matrix(my_vector, 5, 5);
if (my_vector) {
/* trying to access the freed data will invoke undefined behavior */
}
return 0;
}
In the code above, my_vector is not reset to NULL by free_matrix, so the programmer might try to access it and invoke undefined behavior (crash or anything else), whereas in the posted code, the three star free_matrix would reset my_vector to NULL which can be easily tested.

Can anyone explain me how to return a two dimensonal array in C from a function?

I am new to C and during my learning I want to return a two dimensional array from a function, so that I can use it in my main program. Can anyone explain me the same with example. Thanks in advance.
It depends how it is implemented. You can either work with just a one-dimensional array where you know the length of each (row) and the next row begins immediately after the previous one. OR, you can have an array of pointers to arrays. The extra cost though is you need to de-reference two pointers to get to one element of data.
// 2D array of data, with just one array
char* get_2d_ex1(int rows, int cols) {
int r, c, idx;
char* p = malloc(rows*cols);
for (r=0; r<rows; r++) {
for (c=0; c<cols; c++) {
idx = r*cols + c; // this is key
p[idx] = c; // put the col# in its place, for example.
}
}
return p;
}
Declare your function as returning a pointer to a pointer. If we use int as an example:
int **samplefunction() {
int** retval = new int*[100];
for (int i = 1; i < 100; i++) {
retval[i] = new int[100];
}
// do stuff here to retval[i][j]
return retval;
}
Here's an example of how you might create, manipulate and free a "2d array":
#include <stdlib.h>
#define ROWS 5
#define COLS 10
int **create_2d_array(size_t rows, size_t cols)
{
size_t i;
int **array = (int**)malloc(rows * sizeof(int*));
for (i = 0; i < rows; i++)
array[i] = (int*)malloc(cols * sizeof(int));
return array;
}
void free_2d_array(int **array, size_t rows, size_t cols)
{
size_t i;
for (i = 0; i < rows; i++)
free(array[i]);
free(array);
}
int main(void)
{
int **array2d = create_2d_array(ROWS, COLS);
/* ... */
array2d[3][4] = 5;
/* ... */
free_2d_array(array2d, ROWS, COLS);
return 0;
}
To create a "2d array"/matrix, all you have to do is create a dynamic array of pointers (in this case int*) of the size of the rows/width:
int **array = (int**)malloc(rows * sizeof(int*));
Then you set each of those pointers to point to a dynamic array of int of the size of the columns/height:
array[i] = (int*)malloc(cols * sizeof(int));
Note that the casts on malloc aren't required, it's just a habit I have.

Resources