Memory leaking in C, malloc inside function - c

I am trying to create a 2d array of struct grid_t, and am getting memory leak warnings via address sanitiser, and eventually a seg fault in certain conditions.
There may be various points in my code causing this, but I thought knowing what was going wrong here would point me in the right direction to fixing the rest.
I am new to C and thus to memory management, so all feedback is welcome and appreciated!
void createGridArray(atom_t* ATOM) {
ATOM -> grid = (grid_t**) malloc(WIDTH * sizeof(grid_t*));
grid_t *nullGrid = malloc(sizeof(grid_t));
grid_t temp = {NULL, 0};
*nullGrid = temp;
for (int i = 0; i < WIDTH; i++) {
(ATOM -> grid)[i] = malloc(HEIGHT * sizeof(grid_t));
for (int j = 0; j < HEIGHT; j++) {
(ATOM -> grid)[i][j] = *nullGrid;
}
}
//free(nullGrid); <- do I do this now?
return;
}

Firstly, don't cast the return from malloc(). It is not required in C, and can obscure serious errors.
Second, don't hard-code the type into the malloc() call. For example,
ATOM->grid = (grid_t**) malloc(WIDTH * sizeof(grid_t*));
would be replaced by
ATOM->grid = malloc(WIDTH * sizeof(*(ATOM->grid)));
This ensures the memory allocated is of the required size, regardless of what ATOM->grid is a pointer to.
To answer your question, to release all memory, you need to pass every nonNULL pointer returned by malloc() to free(). Exactly once.
So, if you allocate like this
ATOM->grid = malloc(WIDTH * sizeof(*(ATOM->grid)));
grid_t *nullGrid = malloc(sizeof(*nullGrid));
grid_t temp = {NULL, 0};
*nullGrid = temp;
for (int i = 0; i < WIDTH; i++)
{
(ATOM -> grid)[i] = malloc(HEIGHT * sizeof(*((ATOM->grid)[i])));
for (int j = 0; j < HEIGHT; j++) {
(ATOM -> grid)[i][j] = *nullGrid;
}
the one way of deallocating would be
for (int i = 0; i < WIDTH; i++)
{
free((ATOM -> grid)[i]);
}
free(ATOM->grid);
free(nullGrid);
In this case, you cannot safely free(ATOM->grid) before any free((ATOM -> grid)[i]) (unless you store all of the (ATOM->grid)[i] somewhere else, which sort of defeats the point). The individual (ATOM->grid)[i] may be freed in any order (as long as each is released exactly once).
Lastly, check the pointers returned by malloc(). It returns NULL when it fails, and dereferencing a NULL pointer gives undefined behaviour.

Yes, you need to free(nullGrid); here to avoid a memory leak.
But actually you can simplify your code to this:
void createGridArray(atom_t* ATOM) {
ATOM -> grid = (grid_t**) malloc(WIDTH * sizeof(grid_t*));
grid_t nullGrid = {NULL, 0};
for (int i = 0; i < WIDTH; i++) {
(ATOM -> grid)[i] = malloc(HEIGHT * sizeof(grid_t));
for (int j = 0; j < HEIGHT; j++) {
(ATOM -> grid)[i][j] = nullGrid;
}
}
}
There is need for mallocing nullGrid here at all. BTW the return at the end of a void function is implicit.
You wouldn't do this either:
void Foo()
{
...
int *temp = malloc(sizeof(int));
*temp = ...;
...
bar = *temp;
...
free(temp);
}
but rather:
void Foo()
{
...
int temp
temp = ...;
...
bar = temp;
...
}

The C memory allocation is easier when you think it as a "loan".
Somehow, the system loan you some memory when you call malloc(), and you have to give it back with free().

Related

Error with freeing memory in C, visual studio

I am working on a project that I have made use of Calloc and I am trying to free the memory at the end of my main{} function. However, after the program finishes running and I click on the stop, I get this "proj.exe has triggered a breakpoint."
at this set of codes:
while (freeSpace != NULL) {
free(freeSpace++);
}
Here are my codes for allocating memory:
scanf("%d", &SEG);
BLOCKS = 128 / SEG;
for (int k = 0; k < BLOCKS; k++)
{
memory = (int *)calloc(BLOCKS, sizeof(int));
// handle memory allocation failure
}
for (int i = 0; i < BLOCKS; i++)
{
memory[i] = (int *)calloc(SEG, sizeof(int));
// handle memory allocation failure
}
for (int l = 0; l < BLOCKS+5; l++)
{
//freeSpace = (int*)malloc(l * sizeof(int));
freeSpace = (int *)calloc( BLOCKS + 5, sizeof(int));
// handle memory allocation failure
}
for (int o = 0; o < BLOCKS; o++)
{
memorySpace = (int *)calloc(BLOCKS, sizeof(int));
// handle memory allocation failure
}
`
This is the part where I free my memory:
while (freeSpace != NULL) {
free(freeSpace++);
}
Can someone please assist me?
Its really hard to fix your issue because it seems like that these are only a part of your code or it is a prototype?
The following code only based on some 'guess':
int main()
{
scanf("%d", &SEG);
BLOCKS = 128 / SEG;
int* memory = (int *)calloc(BLOCKS+1, sizeof(int*)); // the last is a 'NULL' pointer
memset(memory, 0, sizeof(int*)*BLOCKS+1);
for (int i = 0; i < BLOCKS; i++)
{
memory[i] = (int *)calloc(SEG, sizeof(int));
// handle memory allocation failure
}
while (memory != NULL) {
free(memory++);
}
}
I think you are misunderstanding how pointers work when allocating arrays. Your very first loop has a memory leak in it because you are changing what I am assuming the "memory" pointer is pointing to.
To allocate an array in C would be like below.
int *bigspace;
bigspace = malloc(20 * sizeof(int));
Here we made the pointer "bigspace" point to a new chunk of memory 20 times the size of an integer which is an array. If you did something like below..
int *bigspace;
bigspace = malloc(20 * sizeof(int));
bigspace = malloc(20 * sizeof(int));
This would be no bueno. We are first making "bigspace" pointer point to a chunk of memory (array of ints) and then we are changing what "bigspace" is pointing to by making it point to a new chunk of memory. This means your first chunk of memory does not have a pointer to it anymore and that memory is leaked!
I think the problem is that the value of freeSpace++ is garbage at the end of your allocated memory.
Free a garbage pointer causes the problem.

Matrix memory allocation through a function

I am using these lines to create variable size matrices:
Temp_Mat_0 = (double **)malloc((M)*sizeof(double ));
for (i=0;i<M;i++)
Temp_Mat_0[i] = (double *)malloc((N)*sizeof(double ));
They are working fine but I keep using them repeatedly in my code. I need to convert them to a function where I pass the pointer and the size. I was not able to do it due to pointers mess.
matrixAllocate(Matrix Pointer,rows,colms)
Can you help!
I think you'd be better off with a very simple scheme that allocates your matrix as a single contiguous block.
double **matrix_alloc(int rows, int cols)
{
/* Allocate array of row pointers */
double ** m = malloc(rows * sizeof(double*));
if (!m) return NULL;
/* Allocate block for data */
m[0] = malloc(rows * cols * sizeof(double));
if (!m[0]) {
free(m);
return NULL;
}
/* Assign row pointers */
for(int r = 1; r < rows; r++) {
m[r] = m[r-1]+cols;
}
return m;
}
This has the added bonus that when you free the matrix you don't need to remember how big it was:
matrix_free( double** m )
{
if (m) free(m[0]);
free(m);
}
As an extension to this, you might declare a struct that also keeps track of the number of rows and columns it has. e.g.
struct matrix {
int rows, cols;
double **m;
};
That makes your matrix functions look a little nicer (i.e. you can pass around struct matrix* instead of double**). It has the added bonus that the matrix dimension travels around with the associated data.
Using one contiguous block for your matrix data is generally preferable unless you have huge matrices. And it's very nice if your matrices are small, because you'll get the benefit of better memory locality in your CPU cache -- that means potential for faster code.
they are working fine
They do not seem really fine. Code should be changed to :
Temp_Mat_0 = malloc((M)*sizeof(double*)); //double* instead of double
if (Temp_Mat_0 == NULL)
return;
for (i = 0; i < M; i++){
Temp_Mat_0[i] = malloc((N)*sizeof(double));
if (Temp_Mat_0[i] == NULL){
free(Temp_Mat_0);
return;
}
}
Then, you can use a function like this :
double ** matrix_pointer = matrixAllocate(rows,colms);
where function matrixAllocate returns the pointer it allocated. For example :
matrixAllocate(rows,colms){
Temp_Mat_0 = malloc((rows)*sizeof(double*));
if (Temp_Mat_0 == NULL)
return NULL;
for (i = 0; i < rows; i++){
Temp_Mat_0[i] = malloc((colms)*sizeof(double));
if (Temp_Mat_0[i] == NULL){
free(Temp_Mat_0);
return NULL;
}
}
return Temp_Mat_0;
}
and call it like :
double **matrix pointer;
matrix pointer = matrixAllocate(rows, colms);
Don't forget to free the malloced memory afterwards.
for (i = 0; i < M; i++){
free(Temp_Mat_0[i]);
}
free(Temp_Mat_0);
Note that you should not cast the result of malloc, and you should also check if malloc was successful.

Why does this introduce a memory leak?

I am implementing an Ant Colony Optimization for the Set Covering Problem in C. In my code, I have found a function that causes a memory leak. I am pretty sure this function is the cause of the memory leak, since I have ruled out other functions by testing. Only, I don't understand why this function introduces a memory leak.
To understand this function, I'll describe the Ant struct first. The Ant struct looks like this:
struct Ant {
int* x;
int* y;
int fx;
int** col_cover;
int* ncol_cover;
int un_rows;
double* pheromone;
}
typedef struct Ant ant_t;
The pointers in this struct (such as x, y, col_cover, etc.) are initialized using malloc and freed at the end of the program. Now, the function causing the memory leak is the following:
void localSearch(ant_t* ant) {
int improvement = 1;
ant_t* antcpy = (ant_t*) malloc(sizeof(ant_t));
initAnt(antcpy);
copyAnt(ant, antcpy);
while (improvement) {
improvement = 0;
for (int i = 0; i < inst->n; i++) {
if (antcpy->x[i]) {
removeSet(inst, antcpy, i);
while (!isSolution(antcpy)) {
constructSolution(antcpy);
}
if (antcpy->fx < ant->fx) {
copyAnt(antcpy, ant);
improvement = 1;
eliminate(ant);
} else {
copyAnt(ant, antcpy);
}
}
}
}
free((void*) antcpy);
}
First, I create another instance of the Ant struct (antcpy), using the initAnt function. The copyAnt function does a deep copy of one Ant struct to another Ant struct. My reason for doing a deep copy is the following; I am changing the antcpy and then comparing it to ant. If it turns out better (antcpy->fx < ant->fx), ant is replaced by antcpy. If it turns out worse, antcpy is restored to the values of ant.
These functions are given below:
void initAnt(ant_t* ant) {
ant->x = (int*) malloc(inst->n * sizeof(int));
ant->y = (int*) malloc(inst->m * sizeof(int));
ant->col_cover = (int**) malloc(inst->m * sizeof(int*));
ant->ncol_cover = (int*) malloc(inst->m * sizeof(int));
ant->pheromone = (double*) malloc(inst->n * sizeof(double));
for (int i = 0; i < inst->m; i++) {
ant->col_cover[i] = (int*) malloc(inst->ncol[i] * sizeof(int));
}
}
void copyAnt(ant_t* from, ant_t* to) {
to->fx = from->fx;
to->un_rows = from->un_rows;
for (int i = 0; i < inst->n; i++) {
to->x[i] = from->x[i];
to->pheromone[i] = from->pheromone[i];
}
for (int i = 0; i < inst->m; i++) {
to->y[i] = from->y[i];
to->ncol_cover[i] = from->ncol_cover[i];
for (int j = 0; j < inst->ncol[i]; j++) {
to->col_cover[i][j] = from->col_cover[i][j];
}
}
}
I don't really see why this code causes a memory leak, since I free antcpy at the end of the localSearch function. So, why does this code introduce a memory leak and how can I fix it?
You will have to implement a function freeAnt that before free((void*) antcpy); will release all memory that was allocated in initAnt.
void freeAnt(ant_t* ant) {
for (int i = 0; i < inst->m; i++) {
free(ant->col_cover[i]);
}
free(ant->pheromone);
free(ant->ncol_cover);
free(ant->col_cover);
free(ant->y);
free(ant->x);
}

Malloc affecting random integer value

I'm writing a virtual memory simulator in C, compiling on linux, and I'm getting something rather strange. It takes in a file IO, which I put into an int* plist.
I've printed this "plist" array, and it comes out to
0 100
1 200
2 400
3 300
etc
The problem is that it seems malloc or something is randomly changing plist[3] to 0. It doesn't seem like it should be that way, but I've put a print statement at every line of code to print plist[3], and
tables[i].valid = (char*) xmalloc(num_pages * sizeof(char));
is where it changes. plist[3] = 300 before the line, 0 after it. And it only does this when i = 2. The first 3 rounds of the loop run fine, and on round 3, it changes the values for round 4. I have no idea why, it makes little sense that malloc would change a value in an array that's completely unrelated - is it possible I've gone over some space limit, even though I'm using the heap for basically everything? Would it just change values in random arrays if I did?
for(i = 0; i < 4; i++){
num_pages = plist[i] / P1;
tables[i].page_num = (char**) xmalloc(num_pages * sizeof(char*));
tables[i].valid = (char*) xmalloc(num_pages * sizeof(char));
//initialize page numbers and valid bits
for(j = 0; j < 10; j++){
tables[i].page_num[j] = (char*) xmalloc(16*sizeof(char));
tmp = itoa(i, tmp);
strcat(tables[i].page_num[j], tmp);
strcat(tables[i].page_num[j], "p");
tmp = itoa(j, tmp);
strcat(tables[i].page_num[j], tmp);
tables[i].valid[j] = 0;
}
}
Here's the struct for tables:
typedef struct s_page_table
{
char** page_num;
char* valid;
} t_page_table;
And this is xmalloc (it's just a wrapper to make it easier):
void* xmalloc(int s)
{
void* p;
p = malloc(s);
if (p == NULL)
{
printf("Virtual Memory Exhausted");
exit(1);
}
return p;
}
EDIT: If I take out both lines referencing tables[i].valid, the problem does not exist. plist[3] stays the same. num_pages is always >= 10. I set j to be 0 to 10 just to have less output for debugging purposes.
EDIT 2: If I change valid from a char* to an int* it doesn't work. If I change it to an int, it does.
There are several possibilities, including (but not limited to):
tables[i] is out of bounds;
plist contains a dangling pointer (i.e. it's been deallocated);
plist hasn't been initialised;
plist isn't as large as you think, i.e. plist[3] is out of bounds.
If you can't figure out the problem by looking at the code, valgrind is your friend.
OK. So I believe the problem turned out to be playing with the strings before initializing everything. I'm not entirely certain the reason, maybe someone else can elaborate, but when I encapsulated JUST the initialization in its own function, like only doing mallocs, and then separately created the strings afterwards, the plist variable was unaffected.
For those interested, the encapsulated function looked like this:
t_page_table* table_builder(int* p, int x, int num_tables)
{
t_page_table* ret = xmalloc(num_tables * sizeof(*ret));
int i, tmp, j;
for(i = 0; i < num_tables; i++){
tmp = (p[i]/x);
ret[i].page_num = xmalloc(tmp * sizeof(char*));
ret[i].valid = xmalloc(tmp * sizeof(char));
for(j = 0; j < tmp; j++){
ret[i].page_num[j] = xmalloc(16 * sizeof(char));
ret[i].valid = 0;
}
}
return ret;
}

C Memory Management Issue

I have traced an EXC_BAD_ACCESS to the following allocation and deallocation of memory. It involves the accelerate framework in Xcode. The main issue is that this code is in a loop. If i force the loop to only iterate once then it works fine. But when it loops (7 times) it causes an error on the second iteration. Does any of this look incorrect?
EDIT: *added actual code. This segment runs if I remove certain parts and such but seems to have poor memory management which results in issues
#import <Foundation/Foundation.h>
#include <math.h>
#include <Accelerate/Accelerate.h>
for(int i = 0; i < 8; i++)
{
int XX[M][m]; //M and m are just 2 ints
for(int kk = 0; kk < M; kk++)
{
for (int kk1 = 0; kk1 < m; kk1++)
{
XX[kk][kk1] = [[x objectAtIndex: (kk + kk1 * J)] intValue]; //x is a NSMutableArray of NSNumber objects
}
}
double FreqRes = (double) freqSamp/n;
NSMutableArray *freqs = [[NSMutableArray alloc] initWithCapacity: round((freqSamp/2 - FreqRes) - 1)];
int freqSum = 0;
for(double i = -1 * freqSamp/2; i < (freqSamp/2 - FreqRes); i+= FreqRes)
{
[freqs addObject: [NSNumber numberWithInt: i]];
if(i == 0)
{
freqSum++;
}
}
int num = [x count];
int log2n = (int) log2f(num);
int nOver2 = n / 2;
FFTSetupD fftSetup = vDSP_create_fftsetupD (log2n, kFFTRadix2);
double ffx[num];
DSPDoubleSplitComplex fft_data;
fft_data.realp = malloc(nOver2 * sizeof(double)); //Error usually thrown on this line in the second iteration. Regardless of what I put there. If I add an NSLog here it throws the error on that NSLog
fft_data.imagp = malloc(nOver2 * sizeof(double));
for (int i = 0; i < n; ++i)
{
ffx[i] = [[x objectAtIndex:i] doubleValue];
}
vDSP_ctozD((DSPDoubleComplex *) ffx, 2, &fft_data, 1, nOver2);
vDSP_fft_zripD (fftSetup, &fft_data, 1, log2n, kFFTDirection_Forward);
for (int i = 0; i < nOver2; ++i)
{
fft_data.realp[i] *= 0.5;
fft_data.imagp[i] *= 0.5;
}
int temp = 1;
ffx[0] = abs(fft_data.realp[0]);
for(int i = 1; i < nOver2; i++)
ffx[i] = sqrt((fft_data.realp[i] * fft_data.realp[i]) + (fft_data.imagp[i] * fft_data.imagp[i]));
ffx[nOver2] = abs(fft_data.imagp[0]);
for(int i = nOver2-1; i > 0; i--)
{
ffx[nOver2 + temp] = sqrt((fft_data.realp[i] * fft_data.realp[i]) + (fft_data.imagp[i] * fft_data.imagp[i]));
temp++;
}
//clear Fxx and freqs data
vDSP_destroy_fftsetupD(fftSetup);
free(fft_data.imagp);
free(fft_data.realp);
[freqs release];
}
Your problem could be that you are casting malloc to a value. As you're tagging this c, I'm assuming that you are compiling in c in which case you should see this answer to a previous question as to why casting with malloc is bad:
https://stackoverflow.com/a/1565552/1515720
you can get an unpredictable runtime error when using the cast without including stdlib.h.
So the error on your side is not the cast, but forgetting to include stdlib.h. Compilers may assume that malloc is a function returning int, therefore converting the void* pointer actually returned by malloc to int and then to your your pointer type due to the explicit cast. On some platforms, int and pointers may take up different numbers of bytes, so the type conversions may lead to data corruption.
Regardless though, as the answer says, YOU SHOULD NOT BE CASTING MALLOC RETURNS, because void*'s are safely implicitly converted to whatever you are assigning it to.
As another answerer stated:
vDSP_destroy_fftsetupD(fftSetup);
Could be also free'ing the memory you allocated on accident.
Any chance the destructor of DSPDoubleSplitComplex is freeing up those two allocated blocks?
It could also be that you are only allowed to call vDSP_create_fftsetupD and vDSP_destroy_fftsetupD once during your process's lifetime

Resources