I feel that a piece of code I have would cause a memory leak. I have a data structure with two two-dimensional arrays, one containing ints and one containing pointers to dynamically-allocated objects (sprites). The data structure is a tilemap, and the ints are the numeric index of each location, which are read from a file. I call that index 'tiles'. This tells what kind of tile it is, for behavioral purposes (i.e. player responds differently to water than to dirt or ice). The objects are the sprites to draw at their respective locations. That index is known as 'images'. That index tells the tilemap what sprite to draw at that position.
typedef struct
{
int** tiles;
sprite*** images;
int w, h;
} tilemap;
I have a function that creates a new tilemap, initializes it, and returns it.
tilemap* new_tilemap(int w, int h, const char* filename)
{
tilemap* tm = malloc(sizeof(tilemap));
tm->w = w;
tm->h = h;
/*allocate memory space for the tiles index*/
tm->tiles = malloc(sizeof(int) * h);
int i, j;
for (i = 0; i < h; ++i)
{
tm->tiles[i] = malloc(sizeof(int) * w);
}
/*fill the index with the appropriate data from a file*/
FILE* file = fopen (filename, "rb");
if (file == NULL)
{
printf("Failed to open map %s\n", filename);
}
for (j = 0; j < h; ++j)
{
for (i = 0; i < w; ++i)
{
fscanf(file, "%d", &(tm->tiles[j][i]));
}
}
fclose(file);
/*allocate space for the images*/
tm->images = malloc(sizeof(sprite*) * h);
for (i = 0; i < h; ++i)
{
tm->images[i] = malloc(sizeof(sprite*) * w);
}
/*load images based on what type of tile is at that position*/
for (j = 0; j < h; ++j)
{
for (i = 0; i < w; ++i)
{
switch (tm->tiles[j][i])
{
case 0:
tm->images[j][i] = new_sprite_file("dat/tiles/0.bmp", 1);
break;
case 1:
tm->images[j][i] = new_sprite_file("dat/tiles/1.bmp", 2);
break;
}
tm->images[j][i]->x = i*tm->images[j][i]->w;
tm->images[j][i]->y = j*tm->images[j][i]->h;
}
}
return tm;
}
Then, to free the tilemap and all it's structures I have this function:
void free_tilemap(tilemap* tm)
{
/*loop through and free each of the images in the array*/
int i, j;
for (j = 0; j < tm->h; ++j)
{
for (i = 0; i < tm->w; ++i)
{
free(tm->images[j][i]);
}
}
/*free the actual array*/
free(tm->images);
/*free the tile array?*/
free(tm->tiles);
/*free the entire tilemap structure*/
free(tm);
}
However, I feel that it isn't freeing up all the memory I have allocated, because I used malloc twice on the tiles, but only free'd once. I don't know if this is a problem though, seeing as they are ints, but I think that I may have to loop through the tiles array, free every row, then loop through and free every column (containing the rows), in the same manner as it was allocated. Is that what needs to be done or am I just being ignorant and/or paranoid? The same with the images array. Also, feel free to point out other flaws in my code as I know I'm not the best programmer.
Of course you should mirror the mallocs when you free.
for (i = 0; i < h; ++i)
{
tm->tiles[i] = malloc(sizeof(int) * w);
}
/* Inside free_tilemap. */
for (i = 0; i < h; ++i)
{
free(tm->tiles[i]);
}
free(tm->tiles);
Same goes for the other fors that closely resemble this one. Freeing just tiles doesn't automatically free tiles[0..h] in cascade.
Looking at the code quickly I would say that you are indeed missing the free's on the tiles. I would suggest to use a memory analyzer to find out for yourself. E.g. http://www.cprogramming.com/debugging/valgrind.html
That will give you a good overview of allocated memory, and possible memory leaks when the program exits.
Related
I'm writing a little game in C and I wanted to test it with Valgrind.
Here is a little code example:
#include <stdio.h>
#include <stdlib.h>
typedef struct Game {
int** field;
} Game;
void buildfield(Game* game, int length);
void printfield(Game* game, int length);
void freefield(Game* game, int length);
int main()
{
struct Game* game = NULL;
game = malloc(sizeof (struct Game));
buildfield(game, 10);
printfield(game, 10);
freefield(game, 10);
free(game);
return 0;
}
void buildfield(Game* game, int length)
{
game->field = (int**)malloc((sizeof (int*)) * 20);
int i;
for (i = 0; i < 20; i++) {
game->field[i] = (int*) malloc((sizeof (int)) * length);
}
for (int line = 0; line < length; line++) {
for (int col = 0; col < 81; col++) {
game->field[col][line] = 0;
}
}
}
void printfield(Game* game, int length)
{
for (int i = 0; i < length; i++) {
printf("\n");
for (int j = 0; j < 20; j++) {
printf("%d",game->field[i][j]);
}
}
}
void freefield(Game* game, int length)
{
for (int i = 0; i < length; ++i) {
free(game->field[i]);
}
free(game->field);
}
Valgrind is saying:
HEAP SUMMARY:
==6239== in use at exit: 968 bytes in 22 blocks
==6239== total heap usage: 22 allocs, 0 frees, 968 bytes allocated
Why don't I free the allocations?
"Why don't I free the allocations?"
As noted in comments, there is extra complication in the code caused by use of unexplained values ( magic numbers ) to both create and free memory. For reasons explained in the link, among other problems, this can make matching count of frees with count of allocations difficult. The mis-match in times each of these is called in the reason Valgrind indicated blocks of memory remaining at the end of execution.
The following is your code with suggestions, including those specific to clearly applying the same number of calls to free() as to [m][c]alloc() (I chose to use calloc() here to avoid another loop (or memset()) to initialize memory.)
Note also, you may need to change the values that this example uses for #defines to meet your needs, but you only need to change them in one place, (at top of file.)
typedef struct Game {
int** field;
} Game;
void buildfield(Game *game, int length);
void printfield(Game *game, int length);
void freefield(Game *game, int length);
#define COUNT 20//replace all magic numbers
#define LENGTH 10//(change values of #defines to change shape and size of memory)
int main(void)//use a complete prototype for main
{
struct Game* game = NULL;//pointer needs memory
game = malloc(sizeof (struct Game));
buildfield(game, LENGTH);
printfield(game, LENGTH);
freefield(game, LENGTH);
free(game);
return 0;
}
void buildfield(Game *game, int length)
{ //Note - not optimal to cast return of [c][m]alloc in C (only in C++)
game->field = calloc(COUNT, sizeof(game->field));
int i;
for (i = 0; i < COUNT; i++) {
game->field[i] = calloc(LENGTH, (sizeof (game->field[i])) );
}
}
void printfield(Game *game,int length)
{
for (int i = 0; i < COUNT; i++) {
printf("\n");
for (int j = 0; j < LENGTH; j++) {
printf("%d",game->field[i][j]);
}
}
}
void freefield(Game *game,int length)
{
for (int i = 0; i < COUNT; ++i) {
free(game->field[i]);
}
free(game->field);
}
Well in the function buildfield()
You have alloted 20 blocks of memory
game->field = (int **) malloc(sizeof(int *) * 20);
Hence the most you can access by [] operator is game->field[19]
But in the loop the program tries to access more blocks ahead of game->field[19]
Causing a segmentation fault
And the program crashes then and there. Without ever returning to main() let alone reach the free() statement. So it means your program never completed in the first place and crashed midway.
for (int line = 0; line < length; line++)
{
for (int col = 0; col < 81; col++) //when col becomes 20
{
game->field[col][line] = 0; //this statement will try to access the non-alloted memory block when col is 20
}
}
To check if your program crashes midway add some print statements at the end of the statements related to accessing memory or use a debugger. Because that's the most common source of runtime errors.
Also for this code try to keep in mind the maximum no. of memory blocks alloted that can be accessed by a specific pointer and change the condition of the marked for loop so that it will access memory within the allocation limit that is the no. of blocks you alloted using the malloc function.
The problem here is not the free() not working. But the segmentation fault.
Assuming the code you provided is the exact replica of your code
I'm trying to read in the data from a .bmp image file so that I can manipulate it. However, after I read in the data I get two problems that I feel are related. Firstly, on the call of fclose() I get a sigabrt, and secondly, if I simply comment out the fclose() all the data I read into the structure array is set to 255 even though it was read-in correctly earlier. I'm pretty new to C so this is almost certainly rookie mistake with allocating dynamic memory.
Pixel** readFile(FILE* fp,Header* header,InfoHeader* infoHeader)
{
if(fp == NULL)
{
printf("file not found\n");
return NULL;
}
fread(&header->Type,SHORTSIZE,1,fp);
fread(&header->Size,INTSIZE,1,fp);
fread(&header->Reserved1,SHORTSIZE,1,fp);
fread(&header->Reserved2,SHORTSIZE,1,fp);
fread(&header->Offset,INTSIZE,1,fp);
fread(&infoHeader->Size,INTSIZE,1,fp);
fread(&infoHeader->Width,INTSIZE,1,fp);
fread(&infoHeader->Height,INTSIZE,1,fp);
fread(&infoHeader->Planes,SHORTSIZE,1,fp);
fread(&infoHeader->Bits,SHORTSIZE,1,fp);
fread(&infoHeader->Compression,INTSIZE,1,fp);
fread(&infoHeader->ImageSize,INTSIZE,1,fp);
fread(&infoHeader->xResolution,INTSIZE,1,fp);
fread(&infoHeader->yResolution,INTSIZE,1,fp);
fread(&infoHeader->Colors,INTSIZE,1,fp);
fread(&infoHeader->ImportantColors,INTSIZE,1,fp);
int rows = infoHeader->Height;
int cols = infoHeader->Width;
Pixel** pixelArr = malloc(rows * sizeof(Pixel*));
int i;
for (i = 0; i < cols; i++)
{
pixelArr[i] = (Pixel*) malloc(sizeof(Pixel));
}
int j;
for(i = 0; i < rows; i++)
{
for(j = 0; j < cols; j++)
{
fread(&pixelArr[i][j].Red,CHARSIZE,1,fp);
fread(&pixelArr[i][j].Green,CHARSIZE,1,fp);
fread(&pixelArr[i][j].Blue,CHARSIZE,1,fp);
}
printf("\n");
}
fclose(fp);
return pixelArr;
}
I am struggling with an algorithm to print numbers between 1 and a dynamic variable n into an int.
int n = // dynamic value
int i = 0;
int output[n];
for(i = 0; i < n; i++) {
output[i] = i;
}
However, as n is dynamic, the code won't compile.
Any help would be much appreciated - thanks in advance.
You need to allocate a buffer, or dynamic-sized array, with malloc:
int n = // whatever
int i = 0;
int* output = NULL;
// Allocate the buffer
output = malloc(n * sizeof(int));
if (!output) {
fprintf(stderr, "Failed to allocate.\n");
exit(1);
}
// Do the work with the array
for(i = 0; i < n; i++) {
output[i] = i;
}
// Finished with the array
free(output);
output is a pointer to the beginning of the buffer you allocated, and you can treat it as an array of n ints.
When you're finished with the array, you need to de-allocate the memory with free.
This should work:
int n = // whatever
int i = 0;
int* output = (int*)malloc(sizeof(int)*n);
for(i = 0; i < n; i++) {
output[i] = i;
}
Don't forget to free(output); when you don't need it anymore.
EDIT: Made it C.
If 'n' is changing during runtime, then you could use malloc like suggested in the comments. Then check if you need more space, then automatically realloc more space should it be needed
matrix* make_matrix(size_t width, size_t height, size_t k, options opt){
matrix *m= malloc(sizeof(matrix));
if(m==NULL) return NULL;
m->width = width;
m->height = height;
m->k = k;
/*
Since m->data is a int **, it points to int *,
so I have to allocate a number of int *-sized objects to store in it.
*/
//m->data = malloc(sizeof(int *)*height);
m->data = calloc(height, sizeof(int*));
if(m->data == NULL){
free(m);
return NULL;
}
for(size_t i=0; i < height; i++){
//m->data[i] = malloc(sizeof(int)*width);
m->data[i] = calloc(width, sizeof(int));
if(m->data[i] == NULL){
for(size_t j = 0; j < i; j++) free(m->data[j]);
free(m->data);
free(m);
return 0;
}
/*
for(size_t j = 0; j < width; j++){
m->data[i][j] = 0;
}*/
}
return m;
}
I am generating an 2d array and I used malloc instead of calloc. And it turned out that this is going to be a sparse matrix where most of the elements will be zero. So I decided to use calloc. My question is that do I stil need to keep the if statement
if(m->data[i] == NULL){
for(size_t j = 0; j < i; j++) free(m->data[j]);
free(m->data);
free(m);
return 0;
}
I wrote this because malloc doesn't take care of the stack over flow issue so in case of it fails then I have to free those blocks in reverse order. Do I still keep this code with calloc?
Yes. calloc can (and will) fail just as hard as malloc.
This is not a case of "stack overflow", as you are allocating objects on the heap.
The if is required for both malloc and calloc. What it does is that if you fail half-way through your allocation, it will delete the parts you already have allocated. The order is not important.
In debugging my program with Valgrind, I have discovered a memory leak despite what I thought were effective calls to free. First, the code that is allocating the memory and storing it:
row = malloc(sizeof(Row));
row->columns = malloc(sizeof(char*) * headcnt);
row->numcol = 0;
...
row->numcol = colcnt;
rows = realloc(rows, (rowcnt+1) * sizeof(Row));
rows[rowcnt++] = *row;
The code responsible for attempting to free the memory:
void cleanUp(){
int i = 0;
int j = 0;
for (i = 0; i < rowcnt; i++){
for (j = 0; j < rows[i].numcols; j++){
free(rows[i].columns[j]);
}
free(&rows[i]);
}
free(rows);
exit(0);
}
The declaration of Row:
typedef struct {
char** columns;
unsigned short int numcol;
} Row;
Row* rows = NULL;
Worse still, this program sometimes causes a glibc error at free(&rows[i]) that complains of a double free. I am new to C, and would appreciate any pointers (ahem) someone might have.
Doing rows[rowcnt++] = *row; effectively makes a copy of the memory you allocated. Your array rows should be an array of pointers. Also like Oli Chalesworth pointed out, you free for columns should be a single free for all the columns.
rows = malloc(count * sizeof(Row*)); // This is probably done somewhere
row->columns = malloc(sizeof(char*) * headcnt);
row->numcol = 0;
...
row->numcol = colcnt;
rows = realloc(rows, (rowcnt+1) * sizeof(Row*));
rows[rowcnt++] = row;
Now if your cleanup
void cleanUp(){
int i = 0;
int j = 0;
for (i = 0; i < rowcnt; i++){
free(rows[i]->columns);
}
free(rows);
exit(0);
}
Every call to malloc (or realloc) must be matched with a corresponding call to free. If you dynamically allocate an array thus:
int *p = malloc(sizeof(int) * NUM);
You free it like this:
free(p);
Not like this:
for (int i = 0; i < NUM; i++)
{
free(p[i]);
}
It appears that you are doing this incorrectly. I suspect that your cleanup code ought to be:
void cleanUp(){
int i = 0;
int j = 0;
for (i = 0; i < rowcnt; i++){
for (j = 0; j < rows[i].numcols; j++){
free(rows[i].columns[j]); // Free whatever rows[i].columns[j] points to
}
free(rows[i].columns); // Matches row->columns = malloc(sizeof(char*) * headcnt);
}
free(rows); // Matches rows = realloc(rows, (rowcnt+1) * sizeof(Row));
exit(0);
}
Also, there is no way to match the row = malloc(sizeof(Row));. I suspect that your allocation code ought to be:
row->numcol = colcnt;
rows = realloc(rows, (rowcnt+1) * sizeof(Row));
rows[rowcnt].columns = malloc(sizeof(char*) * headcnt);
rows[rowcnt].numcol = 0;
rowcnt++;
Maybe I'm being dense, but isn't this totally unnecessary? All of your memory will be released as soon as the program exits, anyway.