double free or corruption 3d array in C - c

I get a 'double free or corruption' error while freeing up an 3d array. Can anyone please tell me where is the problem in the code? The size of the array is 2*N*N. Value of N here is 100. Even without casting, same result.
Here is the code:
// Mallocing
double ***h = malloc(2 * (sizeof(double**)));
for(i = 0; i < N; i++) {
h[i] = malloc(N * sizeof(double*));
for(j = 0; j < N; j++) {
h[i][j] = malloc(N * sizeof(double));
}
}
// Freeing
for(i = 0; i < N; i++) {
for(j = 0; j < N; j++) {
free(h[i][j]);
}
free(h[i]);
}
free(h);
The program works fine but at the end I get an error 'double free or corruption (!prev): 0x08cd24f8'
Aborted (core dumped).

For the first dimension, you allocate 2 elements:
double ***h = (double***) malloc(2 * (sizeof(double**)));
But you treat it as if it had N elements:
for(i = 0; i < N; i++) {
h[i] = ...
Change outermost loop comparison on allocation and free to:
for(i = 0; i < 2; i++) {
Also don't cast return value of malloc. Also, your code is missing error handling, and will break if allocation fails.

As fas as I can see you allocate 2 items, then fill N of them.
double ***h = (double***) malloc(2 * (sizeof(double**)));
for(i = 0; i < N; i++) {
h[i] = (double**) malloc(N * sizeof(double*));
....
....
}
You're overwriting not allocated space if N>2...

The problem's here:
double ***h = (double***) malloc(2 * (sizeof(double**)));
for(i = 0; i < N; i++) {
// ...
}
You only malloc 2 elements, and iterate over N.
I guess you wanted to have array of size N*N*N, but you ended up with 2*N*N instead.
So this:
double ***h = (double***) malloc(2 * (sizeof(double**)));
Should be:
double ***h = (double***) malloc(N * (sizeof(double**)));

If the value of N = 100 as in your comment then you need to allocate memory to hold N pointer-to-pointer where you have just 2 .
double ***h = malloc(N * (sizeof(double*)));
Don't cast malloc()

As others have pointed out, the specific problem causing the bug is you treating the dimension with 2 elements as if it had N elements.
The core reason for this however, is obfuscation. There are some rules I would strongly recommend you to follow:
Always allocate multi-dimensional arrays as true arrays allocated in adjacent memory. Reference.
Never allocate multi-dimensional arrays as pointer-to-pointer based lookup-tables that are fragmented all over the heap. Not only are they slower and make the code harder to read, they aren't actually arrays. You can't use them together with memcpy() etc.
Unfortunately there are countless of bad C programming teachers and bad books that preach fragmented pointer-to-pointer lookup-tables. So many programmers have to unlearn this, it is frightening...
Never use more than two levels of indirection in your program. There should never be a reason to do so, all it does is to turn your program less readable (Reference MISRA-C:2012 rule 18.5). This is actually known as "three star programming" and it's not a flattering term.
Never cast the result of malloc, because it is pointless to do so.
What you should do:
double (*array)[Y][Z] = malloc( sizeof(double[X][Y][Z]) );
...
free(array);
Example:
#include <stdio.h>
#include <stdlib.h>
#define X 2
#define Y 3
#define Z 4
int main (void)
{
double (*array)[Y][Z] = malloc( sizeof(double[X][Y][Z]) );
double count = 0.0;
for(int x=0; x<X; x++)
{
for(int y=0; y<Y; y++)
{
for(int z=0; z<Z; z++)
{
array[x][y][z] = count++;
printf("%f ", array[x][y][z]);
}
printf("\n");
}
printf("\n");
}
free(array);
return 0;
}
To compile this, you need a compiler which is not older than 16 years.

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...

Creating a dynamic array of arrays using pointers

I'm trying to create a dynamic array of arrays. So, for example, let's look at Pascal's Triangle:
1
11
121
1331
14641
...
...
This is basically an array of length N, that has at each index an array of i+1.
How exactly do we set that up?
I've tried a little bit using pointers.
I set up an array of pointers like such:
int *arr[N];
Then I need a pointer i to point to an array of i+1, so I did:
int *i = 0;
for(int j = 0; j < N; j++){
int numArr[j+1];
arr[*i] = numArr;
*i++;
}
Am I going the right direction for this? Because I believe I'm supposed to allocate memory for this as I must use free() later. Would I use malloc() for each array initialization?
The code could be made extremely simple, if you know what you're doing:
int *arr = malloc(N * sizeof(int*));
int i;
for (i = 0; i < N; ++i) {
arr[i] = malloc(sizeof(int) * (i + 1));
}
Of course, you'll need corresponding calls to free() further down the line, like this:
for (i = 0; i < N; ++i) {
free(arr[i]);
}
free(arr);

define 5D object with memory allocation

I need to clear memory of 5D object, so first I need to define it with memory allocation.
My previous object definition was:
double I_object[N_GROUPS][NN][NN][NN][NN]={0};
I replaced it by code below and c file compiles but c program crashes :(
I_object=(double *****) malloc(sizeof(double *****)*N_GROUPS);
for(i = 0; i < N_GROUPS; i++){
I_object[i]=(double ****) malloc(sizeof(double****)*NN);
for(j = 0; j < NN; j++){
I_object[i][j]=(double ***) malloc(sizeof(double***)*NN);
for(k = 0; k < NN; k++){
I_object[i][j][k]=(double **) malloc(sizeof(double**)*NN);
for(l = 0; l < NN; l++){
I_object[i][j][k][l]=(double *) malloc(sizeof(double*)*NN);
}
}
}
}
Please let me know if this 5D object definition is wrong or where I can find how to define 5D object using malloc.
You forgot to declare the type of I_object. Also, you need to declare i, j, k and l. Also, I wouldn't cast the result of malloc in C. Furthermore, the indirection levels are wrong in your sizeof() calls, which causes a problem in the last one, where there might be a difference between the sizes of a double and a double*.
With those changes, it looks like this:
#define N_GROUPS 3
#define NN 3
int main() {
double *****I_object = malloc(sizeof(double ****)*N_GROUPS);
for (size_t i = 0; i < N_GROUPS; i++) {
I_object[i] = malloc(sizeof(double***)*NN);
for (size_t j = 0; j < NN; j++) {
I_object[i][j] = malloc(sizeof(double**)*NN);
for (size_t k = 0; k < NN; k++) {
I_object[i][j][k] = malloc(sizeof(double*)*NN);
for (size_t l = 0; l < NN; l++) {
I_object[i][j][k][l] = malloc(sizeof(double)*NN);
}
}
}
}
}
Also, for future questions, I would recommend posting a Minimal, Complete, and Verifiable example. This way, people are much more willing (and capable) to help. For instance, I had to make assumptions about N_GROUPS and NN. Even with low values such as 100 for NN, the memory consumption would already be so high that it will likely cause problems, but without a MCVE, it's hard to tell.
Instead of having array of some pointer to other arrays of some pointers to other arrays of ....
simply use a pointer to array[nn][nn][nn][nn] of doubles.
Something like:
#define NN 2
#define N_GROUPS 4
int main(int argc, char* argv[])
{
double (*I_object)[NN][NN][NN][NN]; // Define pointer
I_object = calloc(N_GROUPS, sizeof * I_object); // Allocate and zero-init memory
I_object[3][1][1][1][1] = 42; // Use as 5D matrix
printf("%f\n", I_object[3][1][1][1][1]);
free(I_object); // Free memory
return 0;
}

Allocating contiguous memory for a 3D array in C

I need to allocate contiguous space for a 3D array. (EDIT:) I GUESS I SHOULD HAVE MADE THIS CLEAR IN THE FIRST PLACE but in the actual production code, I will not know the dimensions of the array until run time. I provided them as constants in my toy code below just to keep things simple. I know the potential problems of insisting on contiguous space, but I just have to have it. I have seen how to do this for a 2D array, but apparently I don't understand how to extend the pattern to 3D. When I call the function to free up the memory, free_3d_arr, I get an error:
lowest lvl
mid lvl
a.out(2248,0x7fff72d37000) malloc: *** error for object 0x7fab1a403310: pointer being freed was not allocated
Would appreciate it if anyone could tell me what the fix is. Code is here:
#include <stdio.h>
#include <stdlib.h>
int ***calloc_3d_arr(int sizes[3]){
int ***a;
int i,j;
a = calloc(sizes[0],sizeof(int**));
a[0] = calloc(sizes[0]*sizes[1],sizeof(int*));
a[0][0] = calloc(sizes[0]*sizes[1]*sizes[2],sizeof(int));
for (j=0; j<sizes[0]; j++) {
a[j] = (int**)(a[0][0]+sizes[1]*sizes[2]*j);
for (i=0; i<sizes[1]; i++) {
a[j][i] = (int*)(a[j]) + sizes[2]*i;
}
}
return a;
}
void free_3d_arr(int ***arr) {
printf("lowest lvl\n");
free(arr[0][0]);
printf("mid lvl\n");
free(arr[0]); // <--- This is a problem line, apparently.
printf("highest lvl\n");
free(arr);
}
int main() {
int ***a;
int sz[] = {5,4,3};
int i,j,k;
a = calloc_3d_arr(sz);
// do stuff with a
free_3d_arr(a);
}
Since you are using C, I would suggest that you use real multidimensional arrays:
int (*a)[sz[1]][sz[2]] = calloc(sz[0], sizeof(*a));
This allocates contiguous storage for your 3D array. Note that the sizes can be dynamic since C99. You access this array exactly as you would with your pointer arrays:
for(int i = 0; i < sz[0]; i++) {
for(int j = 0; j < sz[1]; j++) {
for(int k = 0; k < sz[2]; k++) {
a[i][j][k] = 42;
}
}
}
However, there are no pointer arrays under the hood, the indexing is done by the magic of pointer arithmetic and array-pointer-decay. And since a single calloc() was used to allocate the thing, a single free() suffices to get rid of it:
free(a); //that's it.
You can do something like this:
int ***allocateLinearMemory(int x, int y, int z)
{
int *p = (int*) malloc(x * y * z * sizeof(int));
int ***q = (int***) malloc(x * sizeof(int**));
for (int i = 0; i < x; i++)
{
q[i] = (int**) malloc(y * sizeof(int*));
for (int j = 0; j < y; j++)
{
int idx = x*j + x*y*i;
q[i][j] = &p[idx];
}
}
return q;
}
void deallocateLinearMemory(int x, int ***q)
{
free(q[0][0]);
for(int i = 0; i < x; i++)
{
free(q[i]);
}
free(q);
}
I use it and works fine.

How to malloc 2D arrays? [duplicate]

This question already has answers here:
Allocating 2-D array in C
(2 answers)
Closed 8 years ago.
I need to create a two dimensional array. Presently I created it as
int a[100][100]
but I need to allocate the memory dynamically using malloc in C language. I used the code
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int n=6, m=5, i, j;
int **a = malloc(n * sizeof(int *));
for(i = 0; i < m; i++)
a[i] = malloc(m * sizeof(int));
for( i = 1; i <= n; i++ )
{
for( j = 1; j <= m; j++ )
{
scanf("%d %d",&a[i][j]);
}
}
return 0;
}
but now while inputting the elements into the array it shows SEGMENTATION ERROR.
You say in the comments that n is the number of rows. So you need to allocate n rows each of length m. Therefore, the second for loop condition should be i < n. Also, you should check the return value of malloc for NULL in case it fails to allocate memory. I suggest the following change -
long long **a = malloc(n * sizeof(*a));
for(i = 0; i < n; i++)
a[i] = malloc(m * sizeof(*a[i]));
Please note that a multi-dimensional array is not a fundamentally new type. It's simply an array of elements where each element itself is an array (for a 2D array), an array of arrays (for a 3D) array and so on. If you are using C99, you can allocate your array cleanly and succinctly as
int nrow = 4; // number of rows
int ncol = 8; // number of columns
// define arr to be a pointer to an array of ncol ints, i.e.,
// arr is a pointer to an object of type (int[ncol])
int (*arr)[ncol] = malloc(sizeof(int[nrow][ncol]));
// check the result of malloc for NULL
if(arr == NULL) {
printf("malloc failed to allocate memory\n");
// handle it
}
// do stuff with arr
for(int i = 0; i < nrow; i++)
for(int j = 0; j < ncol; j++)
arr[i][j] = i + j;
// after you are done with arr
free(arr);
You should also go through this - How do I work with dynamic multi-dimensional arrays in C?
You have three errors: The first is that you allocate only 5 secondary arrays, but in the input you loop over 6 of them.
The second problem is that array indices are zero-based, i.e. the index start at zero and goes to the size minus one.
The third problem is that you scan for two numbers (why?), but you provide only one destination pointer to scanf.
you just need
long *a = malloc(100*100*sizeof(long));
if you want one single big block of memory.
if you want an array of long* pointers and then each array to be in a separate block of memory go like this:
long **a = malloc(100*sizeof(long*));
for (i=0; i<100; i++) {
a[i] = malloc(100*sizeof(long));
}
This creates 1 array of long* pointers, and then 1 array of 100 longs of each pointer, but I'm not sure now if you say a[10][15] for example if it would calculate position of the element as if its a continuous block. Check that out. :)
If you have C99 use Variable Length Array
#include <stdio.h>
#include <stdlib.h>
int main(void) {
unsigned rows, cols;
printf("Enter rows and columns: ");
fflush(stdout);
scanf("%u%u", &rows, &cols);
int (*a)[cols]; // pointer to VLA
a = malloc(rows * cols * sizeof a[0][0]);
if (a) {
for (unsigned r = 0; r < rows; r++) {
for (unsigned c = 0; c < cols; c++) {
a[r][c] = r*c;
}
}
printf("the element at [4, 2] is %d\n", a[4][2]);
free(a);
}
return 0;
}
Otherwise, you need to calculate the indexing manually.
There are many problems in your code
First, you need long long a[100][100] but you only allocate enough space for ints
a[i] = malloc(m * sizeof(int));
You're also accessing arrays out-of-bound. Indexes start from 0 to array_length-1.
Another problem is that you scanf 2 int values but only provide the address for 1.
scanf("%d %d",&a[i][j]);
You can allocate a 100-element array of pointers, each points to an array of another 100-element array but that's not good because it takes time to do 100 mallocs, and the resulting memory most probably isn't contiguous, which makes it cache unfriendly. There are also a small memory overhead too because the memory allocator must round it up to the nearest block size and this is most probably powers of 2, which may be large as you allocate more and more elements in the first dimension.
You should declare a 1D array of size 100*100 instead. This will be much faster and improve cache coherency. To get the element at a[i][j] just do a[i*WIDTH + j]
long long* a = malloc(WIDTH*HEIGHT*sizeof(long long));
for (i = 0; i < WIDTH*HEIGHT; i++)
{
scanf("%lld ",&a[i]);
}
for (i = 0; i < HEIGHT; i++)
{
for (j = 0; j < WIDTH; j++)
{
printf("%lld ", a[i*WIDTH + j]);
}
printf("\n");
}

Resources