Free Memory of 2d Array in struct - c

I'm writing a little game in C and I wanted to test it with Valgrind.
Here is a little code example:
#include <stdio.h>
#include <stdlib.h>
typedef struct Game {
int** field;
} Game;
void buildfield(Game* game, int length);
void printfield(Game* game, int length);
void freefield(Game* game, int length);
int main()
{
struct Game* game = NULL;
game = malloc(sizeof (struct Game));
buildfield(game, 10);
printfield(game, 10);
freefield(game, 10);
free(game);
return 0;
}
void buildfield(Game* game, int length)
{
game->field = (int**)malloc((sizeof (int*)) * 20);
int i;
for (i = 0; i < 20; i++) {
game->field[i] = (int*) malloc((sizeof (int)) * length);
}
for (int line = 0; line < length; line++) {
for (int col = 0; col < 81; col++) {
game->field[col][line] = 0;
}
}
}
void printfield(Game* game, int length)
{
for (int i = 0; i < length; i++) {
printf("\n");
for (int j = 0; j < 20; j++) {
printf("%d",game->field[i][j]);
}
}
}
void freefield(Game* game, int length)
{
for (int i = 0; i < length; ++i) {
free(game->field[i]);
}
free(game->field);
}
Valgrind is saying:
HEAP SUMMARY:
==6239== in use at exit: 968 bytes in 22 blocks
==6239== total heap usage: 22 allocs, 0 frees, 968 bytes allocated
Why don't I free the allocations?

"Why don't I free the allocations?"
As noted in comments, there is extra complication in the code caused by use of unexplained values ( magic numbers ) to both create and free memory. For reasons explained in the link, among other problems, this can make matching count of frees with count of allocations difficult. The mis-match in times each of these is called in the reason Valgrind indicated blocks of memory remaining at the end of execution.
The following is your code with suggestions, including those specific to clearly applying the same number of calls to free() as to [m][c]alloc() (I chose to use calloc() here to avoid another loop (or memset()) to initialize memory.)
Note also, you may need to change the values that this example uses for #defines to meet your needs, but you only need to change them in one place, (at top of file.)
typedef struct Game {
int** field;
} Game;
void buildfield(Game *game, int length);
void printfield(Game *game, int length);
void freefield(Game *game, int length);
#define COUNT 20//replace all magic numbers
#define LENGTH 10//(change values of #defines to change shape and size of memory)
int main(void)//use a complete prototype for main
{
struct Game* game = NULL;//pointer needs memory
game = malloc(sizeof (struct Game));
buildfield(game, LENGTH);
printfield(game, LENGTH);
freefield(game, LENGTH);
free(game);
return 0;
}
void buildfield(Game *game, int length)
{ //Note - not optimal to cast return of [c][m]alloc in C (only in C++)
game->field = calloc(COUNT, sizeof(game->field));
int i;
for (i = 0; i < COUNT; i++) {
game->field[i] = calloc(LENGTH, (sizeof (game->field[i])) );
}
}
void printfield(Game *game,int length)
{
for (int i = 0; i < COUNT; i++) {
printf("\n");
for (int j = 0; j < LENGTH; j++) {
printf("%d",game->field[i][j]);
}
}
}
void freefield(Game *game,int length)
{
for (int i = 0; i < COUNT; ++i) {
free(game->field[i]);
}
free(game->field);
}

Well in the function buildfield()
You have alloted 20 blocks of memory
game->field = (int **) malloc(sizeof(int *) * 20);
Hence the most you can access by [] operator is game->field[19]
But in the loop the program tries to access more blocks ahead of game->field[19]
Causing a segmentation fault
And the program crashes then and there. Without ever returning to main() let alone reach the free() statement. So it means your program never completed in the first place and crashed midway.
for (int line = 0; line < length; line++)
{
for (int col = 0; col < 81; col++) //when col becomes 20
{
game->field[col][line] = 0; //this statement will try to access the non-alloted memory block when col is 20
}
}
To check if your program crashes midway add some print statements at the end of the statements related to accessing memory or use a debugger. Because that's the most common source of runtime errors.
Also for this code try to keep in mind the maximum no. of memory blocks alloted that can be accessed by a specific pointer and change the condition of the marked for loop so that it will access memory within the allocation limit that is the no. of blocks you alloted using the malloc function.
The problem here is not the free() not working. But the segmentation fault.
Assuming the code you provided is the exact replica of your code

Related

C - Segmentation Fault Reading Struct and Dynamic2D Array Member

I just started learning C and I wanted to try creating a test program that works with pointers, structures, and arrays, since I still have a hard time understanding them. I created this test file which is a distilled version of a larger project that I'm working on. The test file has a struct with a dynamic 2D array as a member of the struct:
typedef struct {
int ** array;
int rows, cols;
} Smaller;
However, after running the test file the terminal returns the following error:
zsh: segmentation fault ./a.out
I researched what this error means,
" Segmentation fault is a specific kind of error caused by accessing memory that “does not belong to you.” " (Link)
But I'm still confused on how fix this problem. I'm pretty sure I allocated the correct amount of memory for each row and column. It's even more confusing because the terminal doesn't indicate which line the error is. I would appreciate any help on this issue.
Below is the full code:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int ** array;
int rows, cols;
} Smaller;
void printArray (Smaller * s);
int main () {
int x, i, j;
Smaller * sand;
// allocate mem for number of rows
sand->array = malloc (3 * sizeof(int *));
//allocate mem for number of columns
sand->array = malloc(4 * sizeof(int));
sand->array = malloc(4 * sizeof(int));
sand->array = malloc(4 * sizeof(int));
// adding a constant value to the 2D array
for (i = 0; i < 3; i ++) {
for (j = 0; j < 4; j ++) {
sand->array[i][j] = 6;
}
}
printArray(sand);
return 0;
}
void printArray (Smaller * sand) {
printf("Welcome to the printArray function! \n");
int i, j;
for (i = 0; i < 3; i ++)
for(j = 0; j < 4; j ++)
printf("array[%d][%d] = %d \n", i, j, sand->array[i][j]);
}
The problem is, as #tromgy pointed out, you are overwriting the base sand->array with the column arrays instead of assigning them to it. A correct code would look like this:
#include <stdlib.h>
#define NUM_ROWS 3
#define NUM_COLS 4
typedef struct {
int ** array;
int rows;
int cols;
} Smaller;
void print_array(Smaller * s);
int main(void) {
Smaller * sand = malloc(sizeof(Smaller));
if (!sand) return -1; /* allocation failed, abort */
sand->rows = NUM_ROWS;
sand->array = malloc(sizeof(int*[NUM_ROWS]));
if (!sand->array) { /* allocation failed, abort */
free(sand); /* free sand first, though */
return -1;
}
for (size_t i = 0; i < NUM_ROWS; ++i) {
sand->array[i] = malloc(sizeof(int[NUM_COLS]));
if (!sand->array[i]) {
/* free the previous rows */
for (size_t j = 0; j < i; ++j) free(sand->array[j]);
free(sand->array);
free(sand);
return -1;
}
}
/* add a constant value to the array */
for (size_t i = 0; i < NUM_ROWS; ++i) {
for (size_t j = 0; j < NUM_COLS; j ++) {
sand->array[i][j] = 6;
}
}
print_array(sand);
/* Ok, now free everything */
for (size_t i = 0; i < NUM_COLS; ++i) {
free(sand->array[i]);
}
free(sand->array);
free(sand);
/* NOW we may exit */
return 0;
}
As you can see, allocating a structure like this is a lot of work, and you have to free whatever you allocate, so it's probably better to extract it out to a function, something like Smaller * smaller_init(size_t nrows, size_t ncols) and void smaller_destroy(Smaller * s) encapsulating all that work.
I will left an example below so you can compare it to the way you wrote it originally...
About your code:
Declare loop variables inside the for command
May be Smaller do not need to be a pointer
Keep dimensions as variables. It is more flexible
You did not set the values for rows and cols in the struct. And in main() do not use fixed values as 3 and 4 as you did
You should set all cells to different values, not the same. You will feel safer when you see reversible values, like 100*row + column in the example... This way you can see if the loops are ok and all elements are being printed. See this output for printArray():
0 1 2 3
100 101 102 103
200 201 202 203
Each line starts with the line number so you can test it a few times before going on.
make your program test itself. In printArray() for example show the dimensions like this:
printArray[3,4]
0 1 2 3
100 101 102 103
200 201 202 203
See the output of the example
always write the code to free the memory, in the reserve order of the allocation, maybe in a separate function that returns NULL in order to invalidate the pointer back in the calling code, like this
Smaller* freeArray(Smaller* A)
{
printf("\nfreeArray()\n");
for (int i = 0; i < A->rows; i++)
{
free(A->array[i]); // delete lines
printf("row %d free()\n", i);
}
free(A->array); // delete cols
printf("pointer to rows free()\n");
free(A); // delete struct
printf("struct free()\n");
return NULL;
}
This way you know that the pointer sand will not be left pointing to an area that has been free()d. Using such a pointer will crash your program so it may be good to write
sand = freeArray(sand);
output of the example code
printArray[3,4]
0 1 2 3
100 101 102 103
200 201 202 203
freeArray()
row 0 free()
row 1 free()
row 2 free()
pointer to rows free()
struct free()
Example code
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int** array;
int rows, cols;
} Smaller;
void fillArray(Smaller*);
Smaller* freeArray(Smaller*);
Smaller* makeArray(size_t, size_t);
void printArray(Smaller*);
int main(void)
{
int y = 3;
int x = 4;
// sand points to a Smaller
Smaller* sand = makeArray(y, x);
// adding known unique values to cells is easier
fillArray(sand);
printArray(sand); // show values
sand = freeArray(sand); // delete all
return 0;
}
void fillArray(Smaller* A)
{
for (int i = 0; i < A->rows; i++)
for (int j = 0; j < A->cols; j++)
A->array[i][j] = 100 * i + j;
}
Smaller* freeArray(Smaller* A)
{
printf("\nfreeArray()\n");
for (int i = 0; i < A->rows; i++)
{
free(A->array[i]); // delete lines
printf("row %d free()\n", i);
}
free(A->array); // delete cols
printf("pointer to rows free()\n");
free(A); // delete struct
printf("struct free()\n");
return NULL;
}
Smaller* makeArray(size_t y, size_t x)
{
// sand points to a Smaller
Smaller* sand = (Smaller*)malloc(sizeof(Smaller));
sand->rows = y;
sand->cols = x;
// allocate mem for number of rows, that is 'y'
sand->array = malloc(y * sizeof(int*));
// allocate mem for each of the 'x' columns
for (size_t i = 0; i < y; i++)
sand->array[i] = malloc(x * sizeof(int));
return sand;
};
void printArray(Smaller* sand)
{
printf("printArray[%d,%d]\n\n", sand->rows, sand->cols);
for (int i = 0; i < sand->rows; i++)
{
for (int j = 0; j < sand->cols; j++)
printf("%3d ", sand->array[i][j]);
printf("\n");
}
}
About the code
Please SO people do not bother pointing me not to cast the result of malloc(). It is by decision. This common recommendation is a reminiscence of the C-faq of the 90's and now we know that implicit conversions maybe not so good. In fact implicit things may cost you a lot of time: if you malloc() a series of different structs in a program and omit the types if some of them are for example reversed keep in mind that the use of all casts would help you avoid this costly type of mistake...

Debug Error! HEAP CORRUPTION DETECTED in C

I tried to use dynamic allocation and I didnt sucsses to write it without warnings. I get debbug error with the 'free' function:
This is my program:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define size 1
int* symetri(int set1[size], int set2[size]);
int main() {
int* difference;
int set1[size], set2[size];
for (int i = 0; i < size; i++)
scanf("%d", &set1[i]);
for (int i = 0; i < size; i++)
scanf("%d", &set2[i]);
difference = symetri(set1, set2);
free(difference);
return 0;
}
int* symetri(int set1[size], int set2[size])
{
int* new_arr = (int*)malloc(size * sizeof(int));
while (new_arr == NULL)
new_arr = (int*)malloc(size * sizeof(int));
int counter = 0;
bool sym;
for (int i = 0; i < size; i++) {
new_arr[counter] = set1[i];
counter++;
}
new_arr[counter] = -1;
return new_arr;
}
If free crashes with an error message about heap corruption in a program this simple, it's almost certainly because you wrote to memory that doesn't belong to you. And you did, with this line at the end of symetri:
new_arr[counter] = -1;
You need to make your allocation of new_arr another sizeof(int) longer if you want to write to the end after looping over it.

Why do I get a segmentation fault by declaring a 2d array in c?

I am new to threads and I have a program that uses threads to find the minimum number out of a 2d array and later on, it finds the distance that the other elements of the array have from the minimum number and stores them in another array.
The user should enter the size of the array and the number of threads he wants to use.
I tried the program below for 1d array and it worked just fine. When I converted it to work for a 2d array it started crashing and throwing a segmentation fault. I, however, cannot find which part of the 2d declaration is wrong.
Any help is really appreciated.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#include <pthread.h>
struct Parameters
{
// input
int s,p; //n is size of array, p is number of threads
int** array; //array with elements
int start;
int end;
// output
int smallest;
int pos; //position if minimum
int** B; //array that holds the distances
};
void* min(void* args)
{
struct Parameters* p = (struct Parameters*)args;
int **array = p->array;
int **B1 = p->B;
int start = p->start;
int end = p->end;
int smallest = array[start][start];
int pos = p->pos;
int distance;
//find the smallest
for (int i = start; i < end; i++)
{
for(int j = start; j < end; j++)
{
if (array[i][j] < smallest)
{
smallest = array[i][j];
pos = i;
}
}
}
//find the distances
for(int i = 0; i < ((struct Parameters*)args) -> s; i++)
{
for(int j = 0; j < ((struct Parameters*)args) -> s; j++)
{
distance = abs(pos - i);
B1[i][j] = distance;
}
}
params->smallest = smallest;
params->B = B1;
return NULL;
}
int main()
{
int smallest,pos;
int s,p;
struct Parameters *ptr = (struct Parameters *)malloc(sizeof(struct Parameters));
if(ptr == NULL)
{
printf("Not enough. Try again \n");
exit(0);
}
printf("Type s\n");
scanf("%d",&(ptr->s));
printf("Type p\n");
scanf("%d", &(ptr->p));
// declare an array of threads and associated parameter instances
pthread_t threads[(ptr->p)];
struct Parameters thread_parameters[(ptr->p)] ;
int arr[ptr->s][ptr->s];
int B2[ptr->s][ptr->s];
// intialize the array
for(int i=0; i< ptr->s; i++)
{
for(int j=0; j< ptr->s; j++)
{
printf("Type a \n");
scanf("%d",&arr[i][j]);
}
}
// smallest needs to be set to something
smallest = arr[0][0];
// start all the threads
for (int i = 0; i < ptr->p; i++)
{
memcpy(arr, thread_parameters[i].array, sizeof(arr));
thread_parameters[i].s = ptr->s;
memcpy(Bb, thread_parameters[i].B, sizeof(B2));
thread_parameters[i].start = i * (ptr->s / ptr->p);
thread_parameters[i].end = (i+1) * (ptr->s / ptr->p);
pthread_create(&threads[i], NULL, min, &thread_parameters[i]);
}
// wait for all the threads to complete
for (int i = 0; i < ptr->p; i++)
{
pthread_join(threads[i], NULL);
}
// Now aggregate the "smallest" and "largest" results from all thread runs
for (int i = 0; i < ptr->p; i++)
{
if (thread_parameters[i].smallest < smallest)
{
smallest = thread_parameters[i].smallest;
}
}
printf("Smallest is %d\n", smallest);
thread_parameters[ptr->p].B[ptr->s][ptr->s];
for (int i = 0; i < 1; i++)
{
for(int j = 0; j < ptr->s;j++)
{
for(int k = 0; k < ptr->s; k++)
{
printf("Element %d is %d away from min\n",j,thread_parameters[i].B[j][k]);
}
}
}
return 0;
}
Thank you!!
The issue with your code might also come from :
memcpy(arr, thread_parameters[i].array, sizeof(arr));
...
memcpy(Bb, thread_parameters[i].B, sizeof(B2));
as thread_parameters[i].array and thread_parameters[i].B are not allocated, if you are only reading the array it might b fine to only pass them by address
thread_parameters[i].array = arr
but for thread_parameters[i].B you would need to allocate the arrays and perform a deep copy (memcpy would not work)
The below text does not answer the question but does provide some insight on VLA usage
One reason for causing the segmentation with a declaration of a Variable Length Array is that the value is to large to allocate the array on the stack (some compiler choose this option, this choice might have performance reason).
The is not much option to recover cleanly from failure to allocate memory on the stack as there is little way to clean up stack memory during runtime within the same stack context.
You can mitigate the issue by allocating your 2D arrays on the heap instead, some of the strategies are available here(thanks #Lundin) and here.
int** alloc_2d_int_array(size_t rows, size_t cols) {
int **result = malloc(rows * sizeof(int *));
if(result == NULL) {
// could not allocate more memory
return NULL;
}
size_t row_size = cols * sizeof(int);
for(int i=0; i < rows; ++i) {
result[i] = malloc(row_size);
if(result[i] == NULL) {
// could not allocate more memory
// cleanup
return NULL;
}
}
return result;
}
the above implementation have not been tested, but does compile, there are still risk of integer overflow.
Then use the above define function as following:
int **arr = alloc_2d_int_array(ptr->s, ptr->s);
int **B2 = alloc_2d_int_array(ptr->s, ptr->s);
easier implementation (see here(thanks #Lundin))
int **arr = malloc(sizeof(int[ptr->s][ptr->s]);
int **B2 = malloc(sizeof(int[ptr->s][ptr->s]);

Free double pointer using a function

So I have created and allocated memory for a double pointer using the following function:
void mallocDoubleArr(double ***arr, int size)
{
printf("Here: %d", size);
int i, j;
*arr = malloc(size * sizeof(double*));
for(i = 0; i < size; i++)
{
(*arr)[i]= malloc(size*sizeof(double));
for (j = 0; j < size; j++)
{
(*arr)[i][j] = 0;
}
}
}
And I called the function using:
double **G; //Create double pointer to hold 2d matrix
mallocDoubleArr(&G, numNodes);
Now my question is how would I write a function to free the memory?
I tried something like this:
void freeDoubleArr(double ***arr, int size)
{
int i, j;
for (i = 0; i < size; i++)
for (j = 0; j < size; j++)
free((arr)[i]);
free(arr);
}
It seems that you want to pass the address of a pointer to your freeDoubleArr like freeDoubleArr(&G, numnodes) (which I would rather call deleteDoubleArr). Then you need to have
void freeDoubleArr(double ***arrptr, int size)
{
double** arr = *arrptr;
for (int i = 0; i < size; i++)
free(arr[i]);
free (arr);
*arrptr = NULL;
}
However, you could decide that your square matrix is not represented as an array of pointers to arrays, but just as a plain array. Perhaps using flexible array members (of C99 and later) like
struct matrix_st {
unsigned size;
double arr[]; /* flexible array of size*size elements */
};
could be useful, with the convention that  arr is really an array of size*size elements (each being a double).
Then you can define quick access and mutator inline functions.
inline double get_element(struct matrix_st *m, int i, int j) {
assert (m != NULL);
unsigned s = m->size;
assert (i>=0 && i<s && j>=0 && j<s);
return m->arr[s*i+j];
}
inline void put_element(struct matrix_st* m, int i, int j, double x) {
assert (m != NULL);
unsigned s = m->size;
assert (i>=0 && i<s && j>=0 && j<s);
m->arr[i*s+j] = x;
}
When optimizing and with <assert.h> (see assert(3) ...) and compiling with -DNDEBUG the above accessor get_element and mutator put_element would be perhaps faster than your code.
And the matrix creation is just (to create a zero-ed matrix):
struct matrix_st* make_matrix (unsigned size) {
struct matrix_st* m = malloc(sizeof (struct matrix_st)
+ size*size*sizeof(double);
if (!m) { perror("malloc"); exit(EXIT_FAILURE); };
m->size = size;
memset(m->arr, 0, sizeof(double)*size*size);
return m;
}
Then the user could just use one single call to free to free such a matrix.
BTW, if coding on Linux, compile with gcc -Wall -g and use valgrind memory leak detector and gdb debugger.
Shouldn't your free code be more like the following:
void freeDoubleArr(double ***arr, int size)
{
int i;
for (i = 0; i < size; i++)
free((*arr)[i]);
free(*arr);
}
You're not even using the 'j' parameter anywhere so the inner for loop is going to cause it to attempt to free the same area of memory size times. You also need to dereference the pointer that's passed in to get to the one that's malloc'd, in the same way you do when assigning to result of malloc into it.
Also, it would be useful when saying something doesn't work to include what specific errors you are seeing or what makes you think it isn't working properly.

Creating 2D array in single malloc() call

#include <stdio.h>
#include <stdlib.h>
#define MAX_ROWS 5
#define MAX_COLS 5
int globalvariable = 100;
void CreateMatrix(int ***Matrix)
{
int **ptr;
char *cp;
int i = 0;
*Matrix = (int**)malloc((sizeof(int*) * MAX_ROWS) + ((MAX_ROWS * MAX_COLS)*sizeof(int)));
ptr = *Matrix;
cp = (char*)((char*)*Matrix + (sizeof(int*) * MAX_ROWS));
for(i =0; i < MAX_ROWS; i++)
{
cp = (char*)(cp + ((sizeof(int) * MAX_COLS) * i));
*ptr = (int*)cp;
ptr++;
}
}
void FillMatrix(int **Matrix)
{
int i = 0, j = 0;
for(i = 0; i < MAX_ROWS; i++)
{
for(j = 0; j < MAX_COLS; j++)
{
globalvariable++;
Matrix[i][j] = globalvariable;
}
}
}
void DisplayMatrix(int **Matrix)
{
int i = 0, j = 0;
for(i = 0; i < MAX_ROWS; i++)
{
printf("\n");
for(j = 0; j < MAX_COLS; j++)
{
printf("%d\t", Matrix[i][j]);
}
}
}
void FreeMatrix(int **Matrix)
{
free(Matrix);
}
int main()
{
int **Matrix1, **Matrix2;
CreateMatrix(&Matrix1);
FillMatrix(Matrix1);
DisplayMatrix(Matrix1);
FreeMatrix(Matrix1);
getchar();
return 0;
}
If the code is executed, I get the following error messages in a dialogbox.
Windows has triggered a breakpoint in sam.exe.
This may be due to a corruption of the heap, which indicates a bug in sam.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while sam.exe has focus.
The output window may have more diagnostic information.
I tried to debug in Visual Studio, when printf("\n"); statement of DisplayMatrix() is executed, same error message is reproduced.
If I press continue, it prints 101 to 125 as expected. In Release Mode, there is no issue !!!.
please share your ideas.
In C it is often simpler and more efficient to allocate a numerical matrix with calloc and use explicit index calculation ... so
int width = somewidth /* put some useful width computation */;
int height = someheight /* put some useful height computation */
int *mat = calloc(width*height, sizeof(int));
if (!mat) { perror ("calloc"); exit (EXIT_FAILURE); };
Then initialize and fill the matrix by computing the offset appropriately, e.g. something like
for (int i=0; i<width; i++)
for (int j=0; j<height; j++)
mat[i*height+j] = i+j;
if the matrix has (as you show) dimensions known at compile time, you could either stack allocate it with
{ int matrix [NUM_COLS][NUM_ROWS];
/* do something with matrix */
}
or heap allocate it. I find more readable to make it a struct like
struct matrix_st { int matfield [NUM_COLS][NUM_ROWS]; };
struct matrix_st *p = malloc(sizeof(struct matrix_st));
if (!p) { perror("malloc"); exit(EXIT_FAILURE); };
then fill it appropriately:
for (int i=0; i<NUM_COLS; i++)
for (int j=0; j<NUM_ROWS, j++)
p->matfield[i][j] = i+j;
Remember that malloc returns an uninitialized memory zone so you need to initialize all of it.
A two-dimensional array is not the same as a pointer-to-pointer. Maybe you meant
int (*mat)[MAX_COLS] = malloc(MAX_ROWS * sizeof(*mat));
instead?
Read this tutorial.
A very good & complete tutorial for pointers, you can go directly to Chapter 9, if you have in depth basic knowledge.

Resources