Memory leak when rewriteing a 2d array - c

I want to call a function that uses my 2d dynamic array to create another 2d dynamic array and then rewrite the value for my first array. So the code is something like this:
#include <stdio.h>
#include <stdlib.h>
int **bigger(int **A)
{
int i;
int **A2 = (int **)malloc(10 * sizeof(int *));
for(i = 0; i < 10; i++)
A2[i] = (int *)malloc(10 * sizeof(int));
return A2;
}
int main(void)
{
int i;
int **A = (int **)malloc(5 * sizeof(int *));
for(i = 0; i < 5; i++)
A[i] = (int *)malloc(5 * sizeof(int));
A = bigger(A);
for(i = 0; i < 10; i++)
free(A[i]);
free(A);
return 0;
}
If I check it with valgrind --leak-check=yes I get total heap usage: 6 allocs, 3 frees, 240 bytes allocated. How can I solve this memory leak ?

TL:DR, you're not re-writing, you're overwriting.
The problem is in
A = bigger(A);
inside bigger() function, you're allocating new memories and then, storing the same back into A, which makes you lose the pointer to previously allocated memories, thus rendering them unreachable and are not free()-d. Those causes the leak here.
You need to use realloc() for resizing already malloc()ed memory regions.
Otherwise, before you call malloc() again, inside the bigger(), you ought to free() the available memories.

Related

My program crashes when using realloc in C

#include <stdio.h>
#include <stdlib.h>
char **Names;
int size = 2; //Minimum size for 2D array
void main() {
int i;
Names = (char **)malloc(size * sizeof(char *)); // First initaliaion of 2D array in heap
for (i = 0; i < size; i++)
Names[i] = (char *)malloc(20 * sizeof(char));
printf("\nenter");
for (i = 0; i < size; i++)
scanf("%s", Names[i]);
while (1) {
size++;
Names = (char **)realloc(Names, size * sizeof(char *)); //Dynamic allocation of 2D aray
for (i = 0; i < size; i++)
Names[i] = (char *)realloc(Names[i], 20 * sizeof(char));
i = size - 1;
printf("\nenter");
scanf("%s", Names[i]);
for (i = 0; i < size; i++)
printf("\n%s", Names[i]);
}
}
It doesn't crash immediately it depends on the "size" I initialized.
It crashes after 5 allocations for me.
I tried adding free function but it did not seem to help.
After this memory reallocation
size ++;
Names= (char**)realloc(Names,size*sizeof(char *));
the last pointer pf the array of pointers has an indeterminate value because it was not initialized.
As a result the call of realloc for the last pointer in this loop
for (i=0; i<size; i++)
Names[i] = (char*)realloc(Names[i],20*sizeof(char));
invokes undefined behavior.
Before executing the loop you need to initialize the last pointer at least like
Names[size-1] = NULL;
In fact there is no sense to use the for loop because what you need is to allocate memory for the newly added pointer. The allocated memory pointed to by the early created pointers is not being changed in size.
So instead of
for (i=0; i<size; i++)
Names[i] = (char*)realloc(Names[i],20*sizeof(char));
you could just write
Names[size-1] = malloc( 20 * sizeof( char ) );
Pay attention to as you have an infinite loop then the memory reallocation sooner or later can fail.
Also according to the C Standard the function main without parameters shall be declared like
int main( void )

double free or corruption 3d array in 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.

C: Allocating memory confusion

For this code
#include <stdlib.h>
#include <stdio.h>
int *f (int n)
{
int *ptr = malloc (sizeof (int));
*ptr = n;
return ptr;
}
int main()
{
int i;
int **ptr = malloc (sizeof (int *));
ptr[0] = f (0);
for (i = 0; i < 5; ++i)
{
ptr = realloc (sizeof (int *) * (i + 2));
ptr[i + 1] = malloc (sizeof (int));
ptr[i + 1] = f (i + 1);
}
for (i = 0; i < 5; ++i)
{
printf ("%d\n", *ptr[i]);
free (ptr[i]);
}
free (ptr);
return 0;
}
does program allocate twice than it is needed?
Yes, You don't need the malloc in main as it is immediately overwritten on the next line and you leak that memory. Is this a homework question?
EDIT for question change
This is now leaking memory in an odd way.
The first few lines aren't leaking but when you get into the loop you're allocating and assigning randomly. (As a first, realloc takes as it's first arguement a pointer to reallocate, so you're missing ptr in there)
Now you're allocating ptr to be of size 2, then 3 then 4 etc... up to 6. And then immediately leaking that memory as you overwrite the pointer with the call to f()
You could write that all like this:
int i;
int **ptr = malloc (sizeof(int*) * 6);
for (i = 0; i < 6; ++i)
{
ptr[i] = f(i);
}
for (i = 0; i < 6; ++i)
{
printf ("%d\n", *ptr[i]);
free (ptr[i]);
}
free (ptr);
return 0;
As an aside, you should in general try not to allocate memory too often, it is relatively slow. If you can use the stack you should, and if not, try and allocate all the memory you need up front, calling realloc in a loop is a bad idea and should be avoided.
In this specific case you don't need a pointer to a pointer, you could have just allocated one array of 6 integers, with int* array = malloc(sizeof(int) * 6) and then array[0] = 0; which would be easier and better.
Yes, it does allocate twice the needed memory. Also, the value of "ptr" in main is overwrite by return of "f" so you don't even have a chance to free it. You could remove the call to malloc in "main":
int main()
{
int *ptr = f (3);
printf ("%d\n", *ptr);
free (ptr);
return 0;
}

Freeing realloc causing error

I am trying to free my memory allocated in the following program:
include <stdio.h>
#include <stdlib.h>
void main(int argc, char** argv) {
int* x = (int *) malloc(4 * sizeof(int));
int i;
for(i = 0; i < 4; i++) {
x[i] = i;
printf("X[%d] = %d\n", i, x[i]);
}
x = (int *) realloc(x, 4 * sizeof(int));
for(i = 0; i < 8; i++) {
x[i] = i;
printf("X[%d] = %d\n", i, x[i]);
// free(x[i]);
}
free(x);
}
I get the following:
libC abort error: * glibc detected ./a.out: free(): invalid next size (fast): 0x00000000014f8010 **
i tried to free inside the last loop, but that still gives a problem. Where am I going wrong?
realloc() does not increase the allocated memory by the specified amount. It reallocates exactly the requested amount of bytes. So if you want to resize your array to be 8 integers long, you'll need to:
x = realloc(x, 8 * sizeof(int));
Btw, do not cast the returned value of malloc() and realloc() in C:
http://c-faq.com/malloc/mallocnocast.html

what happens to a double pointer when it is passed to a function

Im having some trouble understanding how the pass by value mechanism works in c with pointers. Here is my contrived example...
In my main function, I malloc a pointer to an array of int:
int ** checkMe;
checkMe = malloc(sizeof(int *) * 10);
I understand that this operation sets a side a block of 10 chunks of memory, each block big enough to hold the pointer to an int pointer. I receive back the pointer at the start of this block of 10 chunks.
I have another function that takes that double pointer as an argument:
void test2dArray(int ** arr, int size) {
int i, j;
for (i = 0; i < size; i++) {
// arr[i] = malloc(sizeof(int) * size);
for (j = 0; j < size; j++) {
arr[i][j] = i * j;
}
}
}
Whenever I leave the commented section as is, and try to malloc the space for the int in main like this:
int ** checkMe;
checkMe = malloc(sizeof(int *) * 10);
for (i = 0; i < 10; i++) {
checkMe[i] = malloc(sizeof(int));
}
test2dArray(checkMe, 10);
I get memory clobbering whenever I iterate checkMe after the test2dArray call in main.
But if I malloc the space for the int in test2dArray instead (by uncommenting the commented line above) and change my call from main to this:
int ** checkMe;
checkMe = malloc(sizeof(int *) * 10);
test2dArray(checkMe, 10);
the memory clobbering goes away and I can reference checkMe just fine after the function call.
I understand that checkMe is being passed into test2dArray by value. I think this means that the address that is returned by checkMe = malloc(sizeof(int *) * 10); is copied into the function.
I don't understand why the int *'s that checkMe stores gets lost if I don't malloc the space from within test2dArray
When you are allocating in main you are not allocating for 10 integers,
checkMe[i] = malloc(sizeof(int));
change it to
checkMe[i] = malloc(sizeof(int) * 10);
for (i = 0; i < 10; i++) {
checkMe[i] = malloc(sizeof(int));
}
You are only allocating memory for 1 int in each loop iteration. So you have an array of 10 pointers, each pointing to sizeof(int) bytes of memory.
test2dArray(checkMe, 10);
only works for arrays of 10 pointers pointing to at least 10*sizeof(int) memory. You should change the line above to checkMe[i] = malloc(sizeof(int)*10);
Your bug is the difference between this:
checkMe[i] = malloc(sizeof(int));
and this:
arr[i] = malloc(sizeof(int) * size); // size = 10

Resources