I have this code. What it should do is to allocate a pointer array to genSize img structs. For each of the img structs I'm allocating it's inner pointer array with sizes of imgWidth, imgHeight and byteDepth. So practically I have genSize of img structs, each one of them has imgWidth * imgHeight * byteDepth byte dynamic array. In the first loop I'm allocating space for all of the array fields, in the second one I'm trying to deallocate them the same way, but somehow I'm getting valgrind error:
definitely lost: 282,000 bytes in 94,000 blocks
That size is equal to the total number of pixels of all the images (94000 * 3 (byteDepth)).
I have tried to comment out the the third loop, that is responsible for allocating and freeing the memory for the 3 byte array, both for malloc and free and I was getting this error no more, but obviously, I need to malloc it, so I'll be able to access it and free it later on.
I have followed the same instructions that can be found on the internet, many forum pages, but still I can't see where their code differs from mine and why are my arrays not freeing up.
Minimal working example:
#define imgWidth 50
#define imgHeight 50
#define genSize 40
#define byteDepth 3
struct img {
uint8_t ***bitmap;
uint32_t var;
} img;
int main()
{
struct img *images = malloc(genSize*sizeof(img));
for(int i = 0;i<genSize;i++)
{
images[i].bitmap = malloc(imgWidth*sizeof(uint8_t**));
for (int w = 0; w < imgWidth; w++) {
images[i].bitmap[w] = malloc(imgHeight*sizeof(uint8_t*));
for(int h = 0; h < imgHeight; h++) {
images[i].bitmap[w][h] = malloc(byteDepth * sizeof(uint8_t));
}
}
}
for(int i = 0;i<genSize;i++)
{
for (int w = 0; w < imgWidth; w++) {
for (int h = 0; h < byteDepth; h++) {
free(images[i].bitmap[w][h]);
}
free(images[i].bitmap[w]);
}
free(images[i].bitmap);
}
free(images);
}
EDIT: Obviously there is a typo in the second loop, there should be imgHeight instead of byteDepth. Problem solved
Obviously there is a typo in the second loop, there should be imgHeight instead of byteDepth. Problem solved
Related
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.
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.
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().
First of, I'll admit I don't know much about C and pointers, but I've been reading up and have yet to find a solution. I have also tried some solutions found here on SO but none have worked.
The info to fill the structs, as well as the size of the array, is read from a file. So, I want to declare the array in main(), to use in further processing and pass it by reference to read_p5_info() where it is initialized and filled. 'configs' is to be filled by the configurations() function.
typedef struct pentomino_info pentomino_info;
struct pentomino_info {
char name;
int orientations;
int blocks[5][2];
int configs[8];
};
int read_p5_info(int *npieces, int *matrix_size, pentomino_info **pieces) {
// piece info is read from file
// npiece and matrix_size are also read from the file
// With file I'm testing with, npieces = 12 and matrix_size = 5
*pieces = malloc(*npieces * sizeof *pieces);
for (p = 0 ; p < *npieces ; p++) {
pieces[p] = malloc(sizeof *pieces[p]);
ret = fscanf(fp, "%c %*d %d %d %*d %*d %*f", &pieces[p]->name, &p5_rotations, &p5_flips);
pieces[p]->orientations = p5_rotations * p5_flips;
// read p5 blocks
int b = 0;
for (l = *matrix_size - 1 ; l >= 0 ; l--) {
for (c = 0 ; c < *matrix_size ; c++) {
// p5_char is a char read from the file
if(p5_char == '#' || p5_char == 'X') {
pieces[p]->blocks[b][0]=c;
pieces[p]->blocks[b][1]=l;
b++;
}
}
}
}
return 0;
}
int main() {
int npieces, matrix_size;
pentomino_info *pieces; // array of p5 pieces
int ret;
ret = read_p5_info(&npieces, &matrix_size, &pieces);
// configurations() operates on each piece individually
configurations(matrix_size, &pieces[k]);
}
The pieces I'm talking about are Pentominos. npieces is the number of pentaminos the file has information for, matrix_size is because pentamino_info.blocks has coordinates X,Y of the placement of each block in a matrix_size x matrix_size matrix.
I get segfault at the end of main(). pieces[0] seems fine but still gives me segfault, and the others are just malformed.
I tried to make the code a bit more compact by removing some parts that didn't seemed relevant, if I overdid it let me know. Thanks in advance for any help.
*pieces = malloc(*npieces * sizeof *pieces); allocates the wrong amount of memory. Should be sizeof **pieces. The pattern is P = malloc(N * sizeof *P); as a cognitive cross-check, check that there is one more star on the front of the argument to sizeof.
pieces[p]->x should be (*pieces)[p].x, you make this error in multiple places. In array notation, you wrote pieces[p][0].x but the correct indexing is pieces[0][p].x. The pointer pieces only points to one pointer, which then points to the first element of an array of infos.
If this is confusing I would recommend using "normal" pointers in your function, and then implementing the return-by-reference at the end, e.g.:
int n_pie = 12; // or whatever you read
pentomino_info *pie = malloc(n_pie * sizeof *pie);
// ...
pie[p].orientations = bla;
// ...
*npieces = n_pie;
*pieces = pie;
return 0;
Whats wrong with this function, which is expected to add a row and a column to given 2D array? Matrix is symmetric.
void updateMatrix(double ***mat, int size, double *vec)
{ // mat is sizeXsize matrix, length of vec is size+1
*mat = (double**)realloc(*mat, (size + 1)*sizeof(double*));
(*mat)[size] = (double*)malloc((size + 1)*sizeof(double));
for(int i = 0; i < size + 1; i++) {
(*mat)[size][i] = vec[i];
}
for(int i = 0; i < size; i++) {
(*mat)[i] = (double*)realloc((*mat)[i], (size + 1)*sizeof(double));
(*mat)[i][size] = vec[i];
}
}
Your realloc is returning NULL in the second for loop..
I'm trying to figure out why.
Have you allocated everything before hand? Because chances are you might be passing a non NULL and non malloced pointer to realloc. And that is forbidden/will cause errors
Or, as says #MichaelDorgan , you could just be passing a gigantic size to your function but i sincereley hope you are not trying to allocate a few Go for an array. Otherwise i'm curious as to its use.