I am writing a C program that involves passing 2D arrays between functions changing their size and entries. I decided to use dynamic arrays with pointers for this.
Whenever I free the pointers to an array, I find that I wipe the values held in other arrays. I can successfully change which array a pointer points to. I believe this is an issue with the way I'm freeing my pointers or declaring them. Below is code I'm using to create and free pointers to my arrays.
int** create_array(int m, int n)
{
int i;
int* values = calloc(m * n, sizeof(int));
int** rows = malloc(n * sizeof(int*));
for(i = 0; i < n; i++) {
rows[i] = values + (i * m);
}
return rows;
}
void destroy_array(int** arr)
{
free(arr[0]);
free(arr);
}
OLD CODE to Create and Free Pointers
int** create_array(int m, int n)
{
int i;
int* values = calloc(m * n, sizeof(int));
int** rows = malloc(n * sizeof(int*));
for(i = 0; i < n; i++) {
rows[i] = values + (i * m * sizeof(int));
}
return rows;
}
void destroy_array(int** arr, int m, int n)
{
int i;
for(i = 0; i < n; i++) {
free(arr[i]);
}
free(arr);
}
My program gets a segfault after I destroy the pointers to an array and try to read values from another array. Below is the code where I destroy my pointers to these arrays. positions_last and positions are both arrays that I can read from properly before this point.
positions_last = positions;
printf("- %d %d %d - ", positions_last[0][1], positions_last[1][1], positions_last[2][1]);
fflush(stdout); // this prints fine
destroy_array(positions);
printf("- %d %d %d - ", positions_last[0][1], positions_last[1][1], positions_last[2][1]);
fflush(stdout); // this does not print, I get a segfault at this point
I just did an elementary test which suggests that the issue lies in my current code for creating or destroying arrays (so far as I know).
int** positions2 = create_array(10, 3);
int** positions3 = create_array(10, 3);
printf("%d %d %d", positions3[0][1], positions3[1][1], positions3[2][1]);
fflush(stdout); // This line prints fine
positions3 = positions2;
destroy_array(positions2);
printf("%d %d %d", positions3[0][1], positions3[1][1], positions3[2][1]);
fflush(stdout); // This line triggers a segfault
Anyone have an idea what the issue may be?
You called calloc once and malloc once, but then you're calling free n+1 times (and of course you're freeing the same value, arr[1] n times). There should be exactly one free for each malloc or calloc.
void destroy_array(int** arr)
{
free(arr[0]);
free(arr);
}
This line
rows[i] = values + (i * m * sizeof(int));
should be
rows[i] = values + (i * m);
The reason behind this is that values is a typed pointer, namely pointing to int. Adding 1 to it increases it by 1 * sizeof (int). Your code assumes it would be increased by 1 only.
This are basic pointer arithmetics: http://cslibrary.stanford.edu/104/ ;-)
So you are running into undefined behaviuor even before the 1st call to free().
Also malloc/calloc and free follow the pattern:
One Allocation --> One Freeing
So freeing might look like this:
free(*arr); /* Free what had been allocated to "values". */
free(arr); /* Free what had been allocated to "rows". */
The code you show does differently, as pointed out by zindorsky's answer.
Regarding your edit:
This
positions_last = positions;
does not copy the array, its elements, but just the reference to the array 1st member. SO if you deallocate positions also positions_last points to freed, that is then invalif memory. Accessing it provokes UB, as this lines does:
printf("- %d %d %d - ", positions_last[0][1], positions_last[1][1], positions_last[2][1]);
Lesson learned: In C one cannot copy an array by a simple assignment
Related
My goal is to dynamically reallocate memory for a two dimensional int array in C. I know there are already several questions about that topic, but unfortunately my code does not run properly and i don't know what is going wrong.
First i am allocating memory:
int n = 10;
int m = 4;
int** twoDimArray;
twoDimArray = (int**)malloc(n * sizeof(int*));
for(int i = 0; i < n; i++) {
twoDimArray[i] = (int*)malloc(m * sizeof(int));
}
And initializing the array with integer numbers:
for(int i = 0; i < n; i++) {
for(j = 0; j < 4; j++) {
twoDimArray[i][j] = i * j;
}
}
Then i use realloc() to reallocate memory dynamically:
int plus = 10;
int newArraySize = n + plus;
twoDimArray = (int**)realloc(twoDimArray, newArraySize * sizeof(int));
I am expecting my aray twoDimArray to be accessible at [10][0] now, but when running
printf("twoDimArray[10][0] = %d\n", twoDimArray[10][0]);
i get an "EXC_BAD_ACCESS" runtime error.
Probably i am missing something rather simple, but since i am new to C and can't figure out my mistake. Any help is appreciated.
reallocating the array of pointers is necessary, but then you have only n values that point to something valid. You need to allocate the rest of the sub-arrays because the newly allocated memory points to unallocated/invalid areas. The error is not from accessing the pointer, but from dereferencing it.
You need to add something like:
for(int i = n; i < n+plus; i++) {
twoDimArray[i] = malloc(m * sizeof(int));
}
(same goes for deallocation: first deallocate the arrays in a loop, then deallocate the array of pointers)
Aside:
assigning the result of realloc directly to the original variable can be a problem if realloc returns NULL. Even if it's rare in those resizing cases (Under what circumstances can malloc return NULL?), you should copy the result in a temp variable, check for NULL, and free the old pointer if reallocation failed.
Do I cast the result of malloc?
I allocate a non-square matrix in this way, but I'm not sure if I'm using the deallocation correctly
float **matrix_alloc(int m /* rows */, int n /* columns */)
{
int i;
float **arr = malloc(m*sizeof(*arr));
for(i=0; i<m; i++)
{
arr[i]=malloc(n*sizeof(**arr));
}
return arr;
}
I have tried two way to free the memory
-Attempt A loop rows
void free_mem_mat(int m, float **array) {
int i;
for (i = 0; i < m; i++) {
free(array[i]);
}
free(array);
}
- Attempt B loop columns
void free_mem_mat(int n, float **array) {
int i;
for (i = 0; i < n; i++) {
free(array[i]);
}
free(array);
}
what should I use to free? the way A on the rows or the way B? (I know as written the method is the same I have rewritten this to be most clear possible)
You need one free() for each malloc()*. There were m+1 calls to malloc(); you'd better make m+1 calls to free() too.
Given that as the starting point, option A is the correct solution. However, it is also fair to note that the two functions (option A and option B) are strictly equivalent as long as you pass the m dimension given to the allocation function as the size argument of the deallocation function. The comment in option B is misleading; you're not looping over columns.
Given:
enum { MAT_ROWS = 20, MAT_COLS = 30 };
float **matrix = matrix_alloc(MAT_ROWS, MAT_COLS);
The correct call to free_mem_mat() is:
free_mem_mat(MAT_ROWS, matrix);
* This is an over-simplified statement if you use realloc() or calloc(). You need a free() for each malloc() that was not realloc()'d, and a free() for each realloc() that did not do a free() — by setting the size to 0. Treat calloc() as equivalent to malloc() as far as free() is concerned.
The trouble is that it has many allocations
I prefer this mode
#include <stdio.h>
#include <stdlib.h>
float **matrix_alloc(int m /* rows */, int n /* columns */)
{
int i;
float **arr = malloc(m * sizeof(float *));
*(arr) = malloc(m * n * sizeof(float));
for (i = 0; i < m; i++) {
*(arr + i) = (*(arr) + i * n);
}
return arr;
}
void free_mem_mat(float **array) {
free(*(array));
free(array);
}
int main () {
float **matrix = matrix_alloc(10, 20);
free_mem_mat(matrix);
return 0;
}
more information in:
http://c-faq.com/aryptr/dynmuldimary.html
arr was allocated as an array of m elements, each a pointer to some allocated memory. Therefore, you must free the m pointers in arr. In freeing each, you don't need to mention the size of the thing pointed to.
How to allocate dynamic memory for 2d array in function ?
I tried this way:
int main()
{
int m=4,n=3;
int** arr;
allocate_mem(&arr,n,m);
}
void allocate_mem(int*** arr,int n, int m)
{
*arr=(int**)malloc(n*sizeof(int*));
for(int i=0;i<n;i++)
*arr[i]=(int*)malloc(m*sizeof(int));
}
But it doesn't work.
Your code is wrong at *arr[i]=(int*)malloc(m*sizeof(int)); because the precedence of the [] operator is higher than the * deference operator: In the expression *arr[i], first arr[i] is evaluated then * is applied. What you need is the reverse (dereference arr, then apply []).
Use parentheses like this: (*arr)[i] to override operator precedence. Now, your code should look like this:
void allocate_mem(int*** arr, int n, int m)
{
*arr = (int**)malloc(n*sizeof(int*));
for(int i=0; i<n; i++)
(*arr)[i] = (int*)malloc(m*sizeof(int));
}
To understand further what happens in the above code, read this answer.
It is important that you always deallocate dynamically allocated memory explicitly once you are done working with it. To free the memory allocated by the above function, you should do this:
void deallocate_mem(int*** arr, int n){
for (int i = 0; i < n; i++)
free((*arr)[i]);
free(*arr);
}
Additionally, a better way to create a 2D array is to allocate contiguous memory with a single malloc() function call as below:
int* allocate_mem(int*** arr, int n, int m)
{
*arr = (int**)malloc(n * sizeof(int*));
int *arr_data = malloc( n * m * sizeof(int));
for(int i=0; i<n; i++)
(*arr)[i] = arr_data + i * m ;
return arr_data; //free point
}
To deallocate this memory:
void deallocate_mem(int*** arr, int* arr_data){
free(arr_data);
free(*arr);
}
Notice that in the second technique malloc is called only two times, and so in the deallocation code free is called only two times instead of calling it in a loop. So this technique should be better.
Consider this: Just single allocation
int** allocate2D(int m, int n)
{
int **a = (int **)malloc(m * sizeof(int *) + (m * n * sizeof(int)));
int *mem = (int *)(a + m);
for(int i = 0; i < m; i++)
{
a[i] = mem + (i * n);
}
return a;
}
To Free:
free(a);
If your array does not need to be resized (well, you can, but il will be a bit more complicated), there is an easier/more efficient way to build 2D arrays in C.
Take a look at http://c-faq.com/aryptr/dynmuldimary.html.
The second method (for the array called array2) is quite simple, less painful (try to add the tests for mallocs' return value), and way more efficient.
I've just benchmarked it, for a 200x100 array, allocated and deallocated 100000 times:
Method 1 : 1.8s
Method 2 : 47ms
And the data in the array will be more contiguous, which may speed things up (you may get some more efficient techniques to copy, reset... an array allocated this way).
Rather allocating the memory in many different block, one can allocate this in a consecutive block of memory.
Do the following:
int** my2DAllocation(int rows,int columns)
{
int i;
int header= rows *sizeof(int *);
int data=rows*cols*sizeof(int);
int ** rowptr=(int **)malloc(header+data);
if(rowptr==NULL)
{
return NULL:
}
int * buf=(int*)(rowptr+rows);
for(i=0;i<rows;i++)
{
rowptr[i]=buf+i*cols;
}
return rowptr;
}
That is an unnecessarily complicated way of allocating space for an array. Consider this idiom:
int main(void) {
size_t m = 4, n = 3;
int (*array)[m];
array = malloc(n * sizeof *array);
free(array);
}
I have tried the following code for allocating memory to 2 dimensional array.
#include<stdio.h>
#include<malloc.h>
void main(void)
{
int **p;//double pointer holding a 2d array
int i,j;
for(i=0;i<3;i++)
{
p=(int**)(malloc(sizeof(int*)));//memory allocation for double pointer
for(j=(3*i+1);j<(3*i+4);j++)
{
*p = (int*)(malloc(sizeof(int)));//memory allocation for pointer holding integer array
**p = j;
printf(" %d",**p);//print integers in a row
printf("\n");
p++;
}
}
}
Output of the above code is:-
1 2 3
4 5 6
7 8 9
In order to understand 2 dimensional array in terms of pointers, we need to understand how it will be allocated in memory, it should be something like this:-
1 2 3
1000 --> 100 104 108
4 5 6
1004 --> 200 204 208
7 8 9
1008 --> 300 304 308
from the above, we understand that, when we allocate memory to pointer p which is a double pointer, it is pointing to an array of integers, so in this example, we see that the 0x1000 is pointer p.
This pointer is pointing to integer pointer *p which is array of integers, when memory is allocated inside the inner for loop, during first iteration the pointer is 0x100 which is pointing to integer value 1, when we assign **p = j. Similarly it will be pointing to 2 and 3 in the next iterations in the loop.
Before the next iteration of the outer loop, double pointer is incremented, inside the next iteration, as is seen in this example the pointer is now at 0x1004 and is pointing to integer pointer which is an array of integers 4,5,6 and similarly for the next iterations in the loop.
Try the following code:
void allocate_mem(int*** arr,int n, int m)
{
*arr=(int**)malloc(n*sizeof(int*));
for(int i=0;i<n;i++)
*(arr+i)=(int*)malloc(m*sizeof(int));
}
2d Array dynamically array using malloc:
int row = 4;
int column = 4;
int val = 2;
// memory allocation using malloc
int **arrM = (int**)malloc (row*sizeof(int*));
for (int i=0;i<row;i++)
{
arrM[i] = (int*)malloc(column*sizeof(int));
// insert the value for each field
for (int j =0;j<column;j++,val++)
{
arrM[i][j] = val;
}
}
// De-allocation
for (int i=0;i<row;i++)
{
free(arrM[i]);
}
free(arrM);
arrM = 0;
//
// Now using New operator:
//
int **arr = new int*[row];
int k = 1;
for (int i=0;i<row;i++)
{
arr[i] = new int[column];
// insert the value for each field
for (int j =0;j<column;j++,k++)
{
arr[i][j] = k;
}
}
cout<<"array value is = "<<*(*(arr+0)+0)<<endl;
cout<<"array value is = "<<*(*(arr+3)+2)<<endl;
// Need to deallcate memory;
for (int i=0;i<row;i++)
{
delete [] arr[i];
}
delete []arr;
arr = 0;
After using this function to allocate a 2-d array:
char** make_matrix(int M, int N)
{
char** MAT = (char**)malloc(M * sizeof(char));
for (int i = 0; i < M; i++)
{
MAT[i] = (char*)malloc(N * sizeof(char));
}
return MAT;
}
I found that trying to free(M[0]) causes an assertion failure. All that I can find relating to freeing 2-d arrays use int instead of char. Yet replace every char with int above and the assertion failure disappears. Why is this, and how can I then free the entire 2-d array?
You are allocating too little memory for MAT. Change relevant line to:
char** MAT = (char**)malloc(M * sizeof(char*));
This is because MAT is array of pointers, not characters. Since your code did not allocate enough memory, it was likely writing outside of array bounds and corrupting memory.
It could work with integers because they are bigger, so with some luck you could have been allocating just enough memory (at least on 32 bit machine).
The first malloc call is M * sizeof(char) instead of sizeof(char *). The sizeof(char) would be 1 byte, the size of a char* is likely 4 bytes.
Edit: I see someone beat me to the punch. Accept the other guy's answer.
You should iterate through all the rows of the matrixes and free them first, and then finally the MAT
something like this:
void free_matrix(int M)
{
for (in i = 0; i < M; i++)
{
free(MAT[i]);
}
free(MAT);
}
To release the space (assuming it is correctly allocated), you need a call to free() corresponding to each call to malloc().
void destroy_matrix(char **MAT, int M)
{
for (int i = 0; i < M; i++)
free(MAT[i]);
free(MAT);
}
Your code works when you replace char with int because sizeof(int) == sizeof(int *) on your (32-bit) system. It's largely by coincidence; you'd be in trouble again on a 64-bit system.
I'm getting the double free or corruption error upon executing my code. Essentially, I am just creating a matrix in C (of any RxC dimension, which is why pointers are used), swapping two rows, printing the results, and then attempting to free the memory. When I do not swap the rows, the freeing works perfectly. When I do, it crashes. I've attempted to alter the way the swapping works to no avail. I think it has something to do with the temporary pointer for swapping going out of scope, but I'm not sure if this is the problem and how I would fix it.
MatElement is just a double.
typedef double MatElement;
main:
int main(int argc, char *argv[]) {
MatElement** matrix = matrixAlloc(3,3);
int i;
int j;
for(i = 0; i < 3; i++) {
for(j = 0; j < 3; j++) {
matrix[i][j] = i+j;
}
}
matrixPrint(matrix, "%5.1f", 3, 3);
swapRows(matrix, 0, 2);
matrixPrint(matrix, "%5.1f", 3, 3);
matrixFree(matrix);
return 0;
}
The way the matrices are allocated:
MatElement **matrixAlloc(int nr, int nc) {
int i;
MatElement *ptr;
MatElement **A;
A = malloc(nr * sizeof(MatElement *)); /* array of ptrs */
ptr = calloc(nr * nc, sizeof(MatElement)); /* matrix elements */
for (i = 0; i < nr; i++) /* set row pointers properly */
A[i] = ptr + nc * i;
return A;
}
The way they are freed:
void matrixFree(MatElement **A) {
free(A[0]);
free(A);
}
The way their rows are swapped:
void swapRows(MatElement** G, int pivotRow, int rowExamined) {
MatElement* temp;
temp = G[rowExamined];
G[rowExamined] = G[pivotRow];
G[pivotRow] = temp;
}
Does anyone have any idea about what would be causing this double free() / invalid free()?
At some point, you are swapping the first row of the matrix into another position, so the free(A[0]) in matrixFree() is attempting to free a pointer into the middle of the array, instead of the pointer returned by calloc(). You will need to save that original pointer somewhere so that you can pass it, unmolested, to free().
Your matrix looks like this way :
A has all the pointers to the first element of all the rows. So initially, A[0] points to 0th row, A[1] to 1st row and so on.
So, when you are trying to free the matrix, you know that A[0] points to first row. But at that time you are assuming that your matrix elements are in continuous position and A[0] will always point to initial pointer returned by calloc. But when you swap some rows (specially the 0th with any of other row), then A[0] doesnt point to pointer returned by calloc.
possible solution involves like allocating one more memory slot in A like :
A = malloc( ((nr+1) * sizeof(MatElement )); / array of ptrs */
and then storing original pointer returned by calloc to A[nr].
So, A[nr] will also point to calloc returned pointer.