freeing multidimensional array C - c

I have this struct called Grid that holds a 2d array of strings. I'v been searching on how to free multidimensional arrays properly and can't seem to find the problem with this procedure as valgrind keeps detecting errors and leaked memory. Thanks in advance!
typedef struct Grid{
int N;
int M;
char ***adj;
}TGrid;
TGrid* emptyGrid(int N, int M){
int i,j;
TGrid *Grid = malloc(sizeof(TGrid));
Grid->N = N;
Grid->M = M;
Grid->adj = malloc(N * sizeof(char ***));
for(i = 0; i < N; i++){
Grid->adj[i] = malloc(M * sizeof(char **));
for(j = 0; j < M; j++){
Grid->adj[i][j] = malloc(10 * sizeof(char *));
}
}
return Grid;
}
void freeGrid(TGrid *Grid){
int i, j;
for(i = 0; i < Grid->N; i++){
for(j = 0; j < Grid->M; j++){
free(Grid->adj[i][j]);
}
free(Grid->adj[i]);
}
free(Grid->adj);
free(Grid);
}

The way you malloc memory is incorrect, proper ways should be:
TGrid* emptyGrid(int N, int M){
int i,j;
TGrid *Grid = malloc(sizeof(TGrid));
Grid->N = N;
Grid->M = M;
Grid->adj = malloc(N * sizeof(char **));
for(i = 0; i < N; i++){
Grid->adj[i] = malloc(M * sizeof(char *));
for(j = 0; j < M; j++){
Grid->adj[i][j] = malloc(10 * sizeof(char));
}
}
return Grid;
}
Note that, Grid->adj[i][j] always points to array of 10 char, you can use this:
#include <stdio.h>
#include <stdlib.h>
typedef struct Grid{
int N;
int M;
char (**adj)[10];
}TGrid;
TGrid* emptyGrid(int N, int M){
int i;
TGrid *Grid = malloc(sizeof(TGrid));
Grid->N = N;
Grid->M = M;
Grid->adj = malloc(N * sizeof(char (*)[10]));
for(i = 0; i < N; i++){
Grid->adj[i] = malloc(M * sizeof(char[10]));
}
return Grid;
}
void freeGrid(TGrid *Grid){
int i;
for(i = 0; i < Grid->N; i++){
free(Grid->adj[i]);
}
free(Grid->adj);
free(Grid);
}
int main() {
TGrid* t = emptyGrid(2,3);
freeGrid(t);
return 0;
}
However, since free receives a void* parameter, there must be something else in your code.

The general structure of your code is fine, but the types under sizeof are wrong. The general idiom for malloc-ing memory looks as follows
T *p = malloc(N * sizeof *p);
or, equivalently
T *p = malloc(N * sizeof(T));
Note that in the latter (type-based) variant there's one less asterisk under sizeof than there's is in the recipient pointer type.
That's exactly how it should be in your case as well
Grid->adj = malloc(N * sizeof(char **));
/* Since `Grid->adj` is `char ***`, you should have `char **` under `sizeof` */
...
Grid->adj[i] = malloc(M * sizeof(char *));
/* Since `Grid->adj[i]` is `char **`, you should have `char *` under `sizeof` */
...
Grid->adj[i][j] = malloc(10 * sizeof(char));
/* Since `Grid->adj[i][j]` is `char *`, you should have `char` under `sizeof` */
If that's not what you need, then there must be something wrong with your types. There's no way to say without knowing your intent.
(And I would suggest you use the first approach to specifying sizeof under malloc - use expressions, not types. That way you won't have to count asterisks.)
However, in real life this specific error would typically only result in over-allocated memory. No out-of-bound access or memory leaks should occur. If valgrind reports such errors, there must be something else at work here as well.

It's difficult to see where the problem is since you haven't posted the code that uses the functions.
I want to point out that the calls to malloc need to be changed.
You have:
Grid->adj = malloc(N * sizeof(char ***));
for(i = 0; i < N; i++){
Grid->adj[i] = malloc(M * sizeof(char **));
for(j = 0; j < M; j++){
Grid->adj[i][j] = malloc(10 * sizeof(char *));
}
}
Those calls need to be changed to:
Grid->adj = malloc(N * sizeof(char **));
for(i = 0; i < N; i++){
Grid->adj[i] = malloc(M * sizeof(char *));
for(j = 0; j < M; j++){
Grid->adj[i][j] = malloc(10 * sizeof(char));
}
}
You can avoid such errors by using a coding style as follows:
Grid->adj = malloc(N * sizeof(*(Grid->adj)));
for(i = 0; i < N; i++){
Grid->adj[i] = malloc(M * sizeof(*(Grid->adj[i])));
for(j = 0; j < M; j++){
Grid->adj[i][j] = malloc(10 * sizeof(*(Grid->adj[i][j])));
}
}
A simpler case that uses the same style:
char* cp = malloc(10*sizeof(*cp));

You are not allocating arrays, you are allocating pointer-based look-up tables. The only reason for doing so is if you wish the individual dimensions to have different lengths (such as in an array of strings). If you don't need that, you should never use pointer-to-pointer tables since they are slow, error-prone and needlessly complex.
To allocate an actual 3D array, you would do like this:
char (*array)[Y][Z] = malloc ( sizeof(char[X][Y][Z] );
...
free(array);
To allocate an array of strings, you would do like this:
char** lookup = malloc ( sizeof( char*[N] ) );
for(size_t i=0; i<N; i++)
{
lookup[i] = ...; // assign pointers to strings
}
...
free(lookup);
As a rule of thumb, whenever your program contains more than two levels of indirection, the program design is most likely bad.

Related

Problems when freeing a dynamically allocated 2d array in C

I am desperately trying to free a 2d int array and can't manage to do so.
I guess there's something wrong when i intialize the array?
Could you please help me out?
int rows = 2;
int cols = 3;
int *mfields = (int *) malloc(sizeof(int) * rows * cols);
int **matrix = (int **) malloc(sizeof(int *) * rows);
for (int i = 0; i < rows; i++) {
matrix[i] = mfields + i * cols;
for(int j=0; j<rows;j++) {
matrix[i][j] = (i+1)*(j+1);
}
}
for (int i = 0; i < rows; i++) {
free((matrix[i]));
}
free(matrix);
Thanks in advance,
Christian
Two chunks of memory are allocated:
int *mfields = (int *) malloc(sizeof(int) * rows * cols);
int **matrix = (int **) malloc(sizeof(int *) * rows);
and therefore two chunks of memory should be freed:
free(matrix);
free(mfields);
Freeing multiple chunks of memory, as this loop does:
for (int i = 0; i < rows; i++) {
free((matrix[i]));
is incorrect, as it passes addresses to free that were never returned from malloc.
Generally, it is not good to implement matrices as pointers-to-pointers. This prevents the processor from doing load prediction and impairs performance. If the C implementation(s) that will be used with the code support variable length arrays, then it is preferable to simply allocate one chunk of memory:
int (*matrix)[cols] = malloc(rows * sizeof *matrix);
If variable length array support is not available, then a program should allocate one chunk of memory and use manual calculations to address array elements. While this is may be more work for the programmer, it is better for performance:
int *matrix = malloc(rows * cols * sizeof *matrix);
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
matrix[i*cols + j] = (i+1) * (j+1);

Creating a 2D string array in C

So basically I am trying to read from a huge text file and need to store the data in a 2D string array in C. But I am getting a segmentation fault every time.
Here is the code I use to create the array:
Y = 3
X = 12
char ***some_array=NULL;
some_array = (char ***)malloc(Y * sizeof(char *));
for (int i=0; i<Y; i++)
for (int j=0; j<X; j++){
some_array[i] = (char **)malloc(X * sizeof(char *));
some_array[i][j] = (char *)malloc(16 * sizeof(char));
}
So technically, I am creating a 3D char array for this means. Am I doing something wrong here?
You need to move the allocation of some_array[i] = (char **)malloc(X * sizeof(char *)); from the inner most loop to the outer loop. Moreover, you should not cast the malloc return value. For the final code:
Y = 3
X = 12
char ***some_array = NULL;
some_array = malloc(Y * sizeof(char *));
for (int i = 0; i < Y; i++){
some_array[i] = malloc(X * sizeof(char *));
for (int j = 0; j < X; j++){
some_array[i][j] = malloc(16 * sizeof(char));
}
}
Alternatively you can create a statically allocated array:
char some_array [X][Y][16];
Error is in your loop:
for (int i=0; i<Y; i++) {
some_array[i] = (char **)malloc(X * sizeof(char *));
for (int j=0; j<X; j++){
some_array[i][j] = (char *)malloc(16 * sizeof(char));
}
}
You are supposed to allocate memory to some_array[i] outside the inner loop.

Dynamic Memory allocation for 2D Arrays in C Language

I am trying to solve a Leetcode problem in C.
https://leetcode.com/problems/pascals-triangle/description/
This is my solution to the problem.
I don't think there's an issue with the solution but dynamically allocating memory for a 2D array is getting very complex. Can someone please help me figure out how to correctly allocate memory dynamically to a 2D array. Updated the code based on BLUEPIXY suggestions, I still seem to be getting runtime error.
/**
* Return an array of arrays.
* The sizes of the arrays are returned as *columnSizes array.
* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
*/
int** generate(int numRows, int** columnSizes) {
int i=0,j=0,numColumns =2;
columnSizes = (int **)malloc(numRows * sizeof(int *));
for (i=0; i<numRows; i++)
columnSizes[i] = (int *)malloc( sizeof(int));
int **returnArray = (int **)malloc(numRows * sizeof(int *));
for (i=0; i<numRows; i++)
returnArray[i] = (int *)malloc((i+1) * sizeof(int));
returnArray[0][0] = 1;
*columnSizes =1;
for(i=1;i<numRows;i++)
{
for(j=0;j<numColumns;j++)
{
if(j==0 )
columnSizes[i][j] = returnArray[i-1][j];
else if(j==(numColumns-1))
columnSizes[i][j] = returnArray[i-1][j-1];
else
returnArray[i][j] = returnArray[i-1][j-1] + returnArray[i-1][j];
numColumns++;
}
*(columnSizes+i) = numColumns-1;
}
return returnArray;
}
Problems of new version
(1)
columnSizes = (int **)malloc(numRows * sizeof(int *));
for (i=0; i<numRows; i++)
columnSizes[i] = (int *)malloc( sizeof(int));
should be
*columnSizes = malloc(numRows * sizeof(int));
(※ it is not necessary to cast from void * in C).
(2)
*columnSizes =1;//type of `*columnSizes` is `int *`
should be
**columnSizes = 1;//meant columnSizes[0] = 1; at caller side (main)
(3)
columnSizes[i][j] = returnArray[i-1][j];
...
columnSizes[i][j] = returnArray[i-1][j-1];
should be
returnArray[i][j] = returnArray[i-1][j];
...
returnArray[i][j] = returnArray[i-1][j-1];
because this is typo.
(4)
numColumns++; move to after for(j=0;j<numColumns;j++){ }
(5)
*(columnSizes+i) = numColumns-1;
should be
*(*columnSizes+i) = numColumns-1;//For reasons similar to (2)
The whole fix code:
int** generate(int numRows, int** columnSizes) {
int i=0,j=0,numColumns =2;
*columnSizes = malloc(numRows * sizeof(int));
int **returnArray = (int **)malloc(numRows * sizeof(int *));
for (i=0; i<numRows; i++)
returnArray[i] = (int *)malloc((i+1) * sizeof(int));
returnArray[0][0] = 1;
**columnSizes = 1;
for(i=1;i<numRows;i++)
{
for(j=0;j<numColumns;j++)
{
if(j==0 )
returnArray[i][j] = returnArray[i-1][j];
else if(j==(numColumns-1))
returnArray[i][j] = returnArray[i-1][j-1];
else
returnArray[i][j] = returnArray[i-1][j-1] + returnArray[i-1][j];
}
numColumns++;
*(*columnSizes+i) = numColumns-1;
}
return returnArray;
}
Just do this
int *arr = (int *)malloc(r * c * sizeof(int));
and access the elements like this
int i, j, count = 0;
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
*(arr + i*c + j) = ++count;
OR
If you have the pointer to the pointer, then you get get some help from this code
int main()
{
int i,j;
int **p;
(p)=(int**)malloc(5*sizeof(int*));
for(i=0;i<5;i++)
*(p+i)=(int*)malloc(4*sizeof(int));
for(i=0;i<5;i++)
for(j=0;j<4;j++)
p[i][j]=2;
for(i=0;i<5;i++)
for(j=0;j<4;j++)
printf("%d",p[i][j]);
}
If all you have to do for your programming exercise is print out the results, why bother with any storage at all? Just use the solution here.
How to efficiently calculate a row in pascal's triangle?
Regarding multi-dimensional arrays and C, there is no native support for such a thing. So you have to build your own using one or more 1-D blocks of storage and tricks to index into that storage.
The simplest thing, which #tanuj-yadav suggested works fine for most 2-d arrays is just allocate a nXm-length block of storage and do very simple index arithmetic arr[i*c+j].
The other common approach is arrays of arrays (aka ragged arrays). Which is just like a list of lists, and are naively done with a malloc on each row (or column).

An array of integers and an array of int pointers that point to the first array, does this make sense?

I am experimenting to set up two arrays, let's say array myflags_init and array tripleP; both arrays are two dimenstional, because tripleP is an array of pointers that point to the corresponding index in array myflags_init. Below is my code, and the compiling works fine. I would like to discuss whether this makes sense, as the syntax is a bit crazy to me (e.g. int **tripleP[2] for declaring the two-dimenstional array tripleP of int pointers).
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int m;
for (m = 0; m < 20; m++)
{
int *myflags_init[2];
myflags_init[0] = (int *) calloc(2, sizeof(int));
myflags_init[1] = (int *) calloc(2, sizeof(int));
int r, k;
for (r = 0; r < 2; r++)
{
for (k = 0; k < 10; k++)
{
myflags_init[r][k] = 0; /* initialize the two-d array to 0 */
}
}
int false_num = 0;
int **tripleP[2];
tripleP[0] = (int **) calloc(10, sizeof(int **));
tripleP[1] = (int **) calloc(10, sizeof(int **));
for (r = 0; r < 2; r++)
{
for (k = 0; k < 10; k++)
{
tripleP[r][k] = &myflags_init[r][k]; /* tripleP pointers point to the corresponding index in myflags_init */
}
}
}
return 0;
}
int **tripleP[2];
tripleP[0] = (int **) calloc(10, sizeof(int **));
tripleP[1] = (int **) calloc(10, sizeof(int **));
That works, but shouldn't be written like this. You want to allocate an array of int*, not int**. However it just so happens that both types have the same size (they are both pointers) and thus this will work anyway. But for clarity replace it with this:
int **tripleP[2];
tripleP[0] = (int **) calloc(10, sizeof(int *));
tripleP[1] = (int **) calloc(10, sizeof(int *));
Also the initialization of myflags_init[0] and myflags_init[1] is wrong, because you allocated for 2 elements for each, but try to initialize 10 of them:
myflags_init[0] = (int *) calloc(2, sizeof(int));
myflags_init[1] = (int *) calloc(2, sizeof(int));
//...
for (k = 0; k < 10; k++)
Also you don't need to set them manually to zero. That is exactly what calloc already does for you (in contrast to malloc).
And the outer for-loop seems rather pointless, not to mention the memory leak, because you keep allocating new memory but never call free.

Creating *** object (pointer to pointer to pointer) in C

I am trying to write a function that creates a contiguous block of memory and assigns it to a 3d array. The code works in that it allows me to use the memory, and, when I use data stored in objects created with this function, the results appear correct. However, when I try to free the memory I have allocated with this function, I immediately get a glibc error. Here is the function:
void *** matrix3d(int size, int rows, int cols, int depth) {
void ***result;
int col_size = depth * size;
int row_size = (sizeof(void *) + col_size) * cols;
int data_size = (rows * cols * depth + 1) * size;
int pointer_size = rows * sizeof(void **) + cols * sizeof(void *);
int i, j;
char *pdata, *pdata2;
if((result = (void ***) malloc(pointer_size + data_size)) == NULL)
nerror("ERROR: Memory error.\nNot enough memory available.\n", 1);
pdata = (char *) result + rows * sizeof(void **);
if((long) pdata % (col_size + sizeof(void *)))
pdata += col_size + sizeof(void *) - (long) pdata % (col_size + sizeof(void *));
for(i = 0; i < rows; i++) {
result[i] = pdata;
pdata2 = pdata + cols * sizeof(void *);
for(j = 0; j < cols; j++) {
result[i][j] = pdata2;
pdata2 += col_size;
}
pdata += row_size;
}
return result;
}
It is called in this manner:
double ***positions = (double ***) matrix3d(sizeof(double), numResidues, numChains, numTimesteps);
for(i = 0; i < numResidues; i++)
for(j = 0; j < numChains; j++)
for(k = 0; k < numTimesteps; k++)
positions[i][j][k] = 3.2;
free(positions);
What have I done wrong? Thank you for the help.
What have I done wrong?
Your code is hard to follow (you're playing with pdata a lot) but 99% you're writing past the allocated space and you're messing up the bookkeeping left by glibc.
I can use the data I've written just fine. The only issue is when I
try to use free.
That's because glibc only gets a chance to see you messed up when you call it.
Please excuse my dear Aunt Sally.
int data_size = (rows * cols * depth + 1) * size;
This should be:
int data_size = (rows * cols * (depth + 1)) * size;
Running the code under valgrind identified the error immediately.
What you are doing is one single allocation and then casting it to a tripple-pointer, meaning you have to deal a lot with offsets.
It would probably be better to a larger number of allocations:
char ***result = malloc(sizeof(char **) * rows);
for(i = 0; i < rows; i++) {
result[i] = malloc(sizeof(char *) * cols);
for(j = 0; j < cols; j++) {
result[i][j] = malloc(sizeof(char) * size);
/* Copy data to `result[i][j]` */
}
}
When freeing, you have to free all of the allocations:
for(i = 0; i < rows; i++) {
for(j = 0; j < cols; j++) {
free(result[i][j]);
}
free(result[i]);
}
free(result);
things like this are magnificant candidates to get things wrong
pdata = (char *) result + rows * sizeof(void **);
there is no reason at all to circumvent the address computation that the compiler does for you.

Resources