linear normalization segfault and memory errors - c

I have a segfault in this function...the error message it gives me is this...
*** glibc detected *** /double free or corruption (fasttop): 0x0000000000603250 ***
*** glibc detected *** / memory corruption: 0x00007ffff7dd3710 ***
This is all my code:
struct Image * loadImage(const char* filename)
{
//VARIABLES
struct ImageHeader * hdr2; // on heap, malloc, free
FILE * fptr = fopen(filename, "r");
if (fptr == NULL)
{
return NULL;
}
int retval;
hdr2 = malloc(sizeof(struct ImageHeader));
if (hdr2 == NULL)
{
free(hdr2);
fclose(fptr);
return NULL;
}
retval = fread(hdr2, sizeof(struct ImageHeader), 1, fptr);
if (retval != 1)
{
free(hdr2);
fclose(fptr);
return NULL;
// error
}
if (hdr2 -> magic_bits != ECE264_IMAGE_MAGIC_BITS)
{
free(hdr2);
fclose(fptr);
return NULL;
// error
}
if (hdr2->width == 0||hdr2->height ==0)
{
free(hdr2);
fclose(fptr);
return NULL;
// error
}
struct Image * img = NULL;
img = malloc(sizeof(struct Image));
if(img == NULL)
{
fclose(fptr); // free(img);
return NULL;
//do something
}
img -> width = hdr2 -> width;
img ->height=hdr2->height;
img -> comment = malloc(sizeof(char) * (hdr2->comment_len));
img -> data = malloc(sizeof(uint8_t) * hdr2->width * hdr2->height);
retval = fread(img->comment, sizeof(char), hdr2->comment_len, fptr);
if(img -> comment == NULL)
{
free(hdr2);
free(img->data);
free(img->comment);
free(img);
fclose(fptr);
return NULL;
//do something, don't forget to free whatever you have allocated
}
//lookg at the img-> comment (should free)
if (retval != hdr2->comment_len)
{
free(hdr2);
free(img->data);
free(img->comment);
free(img);
fclose(fptr);
return NULL;
// error
}
/*
if(img->comment[hdr2->comment_len-1]=='\0')/////////////////////////THIS IS THE PROBLEM AREA
{
free(hdr2);
free(img->data);
free(img->comment);
free(img);
fclose(fptr);
return NULL;
}*/
if(img->data==NULL)
{
free(hdr2);
free(img->comment);
free(img);
fclose(fptr);
return NULL;
}
retval = fread(img->data, sizeof(uint8_t),hdr2->width * hdr2->height, fptr);
if (retval != (hdr2->width * hdr2->height))
{
free(hdr2);
free(img->data);
free(img->comment);
free(img);
fclose(fptr);
return NULL;
}
uint8_t j = 0;
if(fread(&j, sizeof(uint8_t),2,fptr)==2)
{
free(hdr2);
free(img->data);
free(img->comment);
fclose(fptr);
}
retval = fread(img ->data, sizeof(uint8_t), hdr2->width * hdr2->height +1, fptr);
if(retval==hdr2->width*hdr2->height+1)
{
free(hdr2);
free(img);
//error
fclose(fptr);
return NULL;
}
fclose(fptr);
return (img);
}
void freeImage(struct Image * image)
{
if(image!=NULL)
{
free(image->data);
free(image->comment);
}
free(image);
}
void linearNormalization(struct Image * image)
{
int index1 = 0;
int index2 = 0;
//int totaldata = image->height * image->width;
int max = 0;
int min = 255;
// if(image -> data[i] > max)
// set max equal to this image
for(index1=0; index1<(image->height * image->width); index1++)
{
if(image->data[index1] > max)
{
max= image->data[index1];
}
if(image->data[index1]<min)
{
min = image->data[index1];
}
}
for(index2 = 0; index2<(image->height * image->width);index2++)
{
image->data[index2] = (image->data[index2]- min) * 255.0 / (max - min);
}
}
I marked the area that is giving me issues...when I leave it in my function does not output the correct data, but does not get a segfault. Can someone tell me what this error code means with respect to that line?

The error message means you are using free on a pointer that you have already freed. The problem is that this kind of error is a bit difficult to find since using free only tells the SO that the memory is free to be used if it needs, but it does not necessarily prevents you from accessing that memory. For example:
int *a = malloc(sizeof(int));
*a = 5;
free(a);
printf("%d", *a);
Will not generate an error, and if you try to free a again, then you will get an error of double free.
From the man pages, free has undefined behaviour if you try to double free something, but if you try free(NULL) there will be no errors. So instead of using a bunch of if's to control what pointers you have to free, just use:
free(ptr);
ptr = NULL;
This way, if you try to free again you won't get and error.

Here's a couple of errors:
uint8_t j = 0;
if(fread(&j, sizeof(uint8_t),2,fptr)==2)
There is surely not room for two uint8_t's in j
retval = fread(img ->data, sizeof(uint8_t), hdr2->width * hdr2->height +1, fptr);
You have a +1 there, but you have not allocated room for that byte when you allocated img->data
For additional help, run your program in valgrind , it is of great help when tracking down bugs such as these.

Both what nos cenouro have pointed out are valid things. Instead of picking all your memory errors apart piece by piece though. Try this thing called Valgrind. It runs your whole program and checks for memory errors everywhere. It's really a life saver.

Related

making malloc function doesn't work correctly?

Hi i wrote a simple malloc and free function. The idea is basically from "The C Programming language". Now i have the problem like if I malloc 3 times and i free it in the same order. My allocp is near to the end but the whole memory is free. I give you my example now. My problem is with the 3 frees. Like when i free 4, 3, 2 its ok because you free the allocp down in the correct order, but i don't know how to solve my problem.
Any ideas?
Thanks for your help :)
#include "mystdlib.h"
#include <stdio.h>
#define ALLOCSIZE 1048576 /* Groeße des verfuegbaren Speichers */
static char allocbuf[ALLOCSIZE]; /* Speicher fuer mymalloc */
static char *allocp = allocbuf; /* next free position */
void *mymalloc(size_t size) {
if(allocp + size <= allocbuf + ALLOCSIZE) {
allocp += size;
return (allocp - size);
}
else {
return NULL;
}
}
void myfree(void *ptr) {
if(ptr >= (void*)allocbuf && ptr < (void*)allocbuf + ALLOCSIZE) {
allocp = ptr;
}
}
int main(){
char *buf1 = mymalloc(900000);
if (buf1 == NULL) {
printf("Error 404, allocated memory not found...\n");
return -1;
}
myfree(buf1);
char *buf2 = mymalloc(500000);
char *buf3 = mymalloc(400000);
char *buf4 = mymalloc(300000);
if (buf2 == NULL || buf3 == NULL) {
printf("Fix your mymalloc!\n");
return -1;
}
if (buf4 == NULL) {
printf("This was supposed to happen. Very good!\n");
} else {
printf("Nope. That's wrong. Very wrong.\n");
return -1;
}
myfree(buf2);
myfree(buf3);
myfree(buf4);
char *buf5 = mymalloc(900000);
if (buf5 == NULL) {
printf("You got so far, but your error free journey ends here. Because an error occured.\n");
return -1;
}
char *buf6 = myrealloc(buf5, 500000);
myfree(buf6);
printf("Congrats, you passed all tests. Your malloc and free seem to work\n");
}

Reading from a file all elements within it in C

So I need to write a function that reads all the elements inside a bit file. The point is that I don't know how many elements there could be inside, but I know what type of elements are. So I tried to write this function:
void loadData(Parallelogram **array) {
FILE *data; long size;
//int numberOfElements = 0;
int numberOfObjects = 0;
if ((data = fopen(name, "rb"))!=NULL) {
fseek(data, 0, SEEK_END);
size = ftell(data);
fseek(data, 0, SEEK_SET);
if (size<(long)sizeof(Parallelogram)) {
printf("The file is empty try to open another file maybe");
} else {
Parallelogram *tempArray;
numberOfObjects = size/sizeof(Parallelogram);
tempArray = realloc(*array, numberOfObjects*sizeof(Parallelogram));
if (tempArray==NULL) {
printf("There was an error reallocating memory");
} else { *array = tempArray; }
fread(*array, sizeof(Parallelogram), numberOfObjects, data);
}
}
fclose(data);
}
The elements are struct objects of type Parallelogram, storing a few floats.
The commented out part was me trying another method form another question but not understanding the real mechanism. Anyways when I call the function the array is empty. What am I getting wrong?
EDIT: As requested this is the main function where I call the function loadData()
int main() {
Parallelogram *paraArray = NULL;
loadData(&paraArray);
}
EDIT: complete function more or less like the OP's.
You may do something like:
void loadData(Parallelogram **array, size_t * n) {
FILE *data;
if ((data = fopen("file.bin", "rb"))!=NULL) {
Parallelogram buffer[100]; // may be malloc'd
size_t chunk_size = 100;
size_t read_size = 0;
size_t number_of_objects = 0;
Parallelogram *aux = NULL;
*array = NULL;
while ((read_size = fread(buffer, sizeof *buffer, chunk_size, data)) > 0) {
aux = realloc(*array, (number_of_objects + read_size) * sizeof *buffer);
if (aux == NULL) {
// ERROR
free(*array);
// clean, break/exit
}
*array = aux;
memcpy(*array + number_of_objects, buffer, read_size*sizeof *buffer);
number_of_objects += read_size;
}
// check file for errors (ferror()) before exit
fclose(data);
*n = number_of_objects;
}
}

realloc: invalid checksum for freed object

I have an error using realloc to replace malloc.
This code below runs OK on my computer.
int vector_grow(Vector* vec) {
unsigned long newcap;
int * newarr;
if (0 == vec->cap) {
vec->arr = (int*)malloc(START_CAPACITY * sizeof(*vec->arr));
if (NULL == vec->arr)
return -1;
vec->cap = START_CAPACITY;
return 0;
}
newarr = malloc (newcap * sizeof(*vec->arr));
if (NULL == newarr)
return -1;
memcpy (newarr, vec->arr, vec->len * sizeof(*vec->arr));
free (vec->arr);
vec->arr = newarr;
vec->cap = newcap;
return 0;
}
I want to change the malloc to realloc, but the error occurs.
int vector_grow(Vector* vec) {
unsigned long newcap;
if (0 == vec->cap) {
vec->arr = (int*)malloc(START_CAPACITY * sizeof(*vec->arr));
if (NULL == vec->arr)
return -1;
vec->cap = START_CAPACITY;
return 0;
}
newcap = 2 * vec->cap;
if ((vec->arr = (int*)realloc(vec->arr, newcap * sizeof(int))) == NULL)
return -1;
return 0;
}
It says
malloc: *** error for object 0x7fca64c02598: incorrect checksum for freed object - object was probably modified after being freed.
I don't know any difference between those two snippets of code, if you know what causes the error, please tell me! Thank you very much!
Bug in missing vec->cap = in updated code certainly contribute to various calls to malloc() and calling code's misuse of data.
int vector_grow(Vector* vec) {
unsigned long newcap;
if (0 == vec->cap) {
... // not important to show the bug
}
newcap = 2 * vec->cap;
if ((vec->arr = (int*)realloc(vec->arr, newcap * sizeof(int))) == NULL)
return -1;
// Add missing update
vec->cap = newcap;
return 0;
}
Also better to test for allocation success
void *p = realloc(vec->arr, sizeof *(vec->arr) * newcap);
if (p == NULL) {
return -1;
}
vec->arr = p;
vec->cap = newcap;
The only scenario where I can imagine such error message is when you actually modify the pointer, for example
int *x = malloc(2 * sizeof *x);
if (x != NULL) {
x = x + 1;
free(x);
}
The pointer that MUST be passed to free() MUST had been returned by malloc()/calloc()/realloc(), passing any other pointer including a pointer to the same data but at a different position like x in the example above is undefined behavior.

Another way to do cleanup in C?

Consider this program:
int main(void)
{
int* i = malloc(sizeof(int));
int* j = malloc(sizeof(int));
}
However this is a naive approach, because malloc may fail and the pointers are not free'd.
So you can do this:
int main(void)
{
int* i;
int* j;
if ((i = malloc(sizeof(int)) < 0)
{
return -1;
}
if ((j = malloc(sizeof(int)) < 0)
{
free(i);
return -1;
}
free(i);
free(j);
}
However I consider this very error-prone. Consider having to assign 20 pointers, in the last malloc error case, you have to free 19 variables and then return -1.
I also know atexit, which can help me to write it like this:
int* i;
int* j;
void del_i(void)
{
free(i);
}
void del_j(void)
{
free(j);
}
int main(void)
{
if ((i = malloc(sizeof(int)) < 0)
{
return -1;
}
else
{
atexit(del_i);
}
if ((j = malloc(sizeof(int)) < 0)
{
return -1;
}
else
{
atexit(del_j);
}
}
Which is better, but I dislike having to declare all pointers as global. Is there some way to combine these two approaches, basically:
Having destructors for pointers, which can be either executed directly or be used with atexit.
Having pointers local to functions.
free on NULL is defined to be a safe no-op. So a non-jumping variation could be:
int *i = malloc(sizeof(int));
int *j = malloc(sizeof(int));
if(i && j)
{
// do some work
}
free(i);
free(j);
First, this will not detect malloc failure:
if ((i = malloc(sizeof(int)) < 0)
{
return -1;
}
malloc returns NULL on failure, not a negative number.
Second, atexit is good for cleaning up static and global objects. It is not a good idea to make local objects global only to use them inside atexit.
A better approach is to make a struct for all related pointers that you need to allocate in an all-or-nothing unit, define a function for freeing them all at once, and write a function that allocates them one by one with memory checking on each allocation:
typedef struct AllOrNothing {
double *dPtr;
int *iPtr;
float *fPtr;
size_t n;
} AllOrNothing;
void freeAllOrNothing(AllOrNothing *ptr) {
free(ptr->dPtr);
free(ptr->iPtr);
free(ptr->fPtr);
free(ptr);
}
int allocateAllOrNothing(size_t n, AllOrNothing **res) {
*res = malloc(sizeof(AllOrNothing));
if (*res == NULL) {
return -1;
}
// Freeing NULL is allowed by the standard.
// Set all pointers to NULL upfront, so we can free them
// regardless of the stage at which the allocation fails
(*res)->dPtr = NULL;
(*res)->iPtr = NULL;
(*res)->fPtr = NULL;
(*res)->n = n;
(*res)->dPtr = malloc(n*sizeof(double));
if ((*res)->dPtr == NULL) {
free(*res);
*res = NULL;
return -1;
}
(*res)->fPtr = malloc(n*sizeof(float));
if ((*res)->fPtr == NULL) {
free(*res);
*res = NULL;
return -1;
}
(*res)->iPtr = malloc(n*sizeof(int));
if ((*res)->iPtr == NULL) {
free(*res);
*res = NULL;
return -1;
}
return 0;
}
int main(void)
{
int* i = NULL; // Init with NULL otherwise free on none NULL possible
int* j = NULLL;
if (!(i = malloc(sizeof(int)))
{
goto exit;
}
if (!(j = malloc(sizeof(int)))
{
goto exit;
}
...
exit:
free(i);
free(j);
...
return err;
}
This is something you can solve with goto statements.
int main(void)
{
int* i = NULL;
int* j = NULL;
bool success = false;
do {
i = malloc(sizeof(int));
if (NULL == i) break;
j = malloc(sizeof(int));
if (NULL == j) break;
success = true;
} while (0);
if (!success)
{
printf("Something failed!");
}
else
{
printf("All succeeded!");
// Do more work
}
free(i);
free(j);
return (success? 0 : 1);
}
Avoid multiple exit points. Avoid interlacing allocation and error handling. Follows a clean order of operation:
Declare, allocate and initialize resources..
If all successful, do the task.
Clean-up.
Return status.
// Do all allocations first, test their `NULL`-ness, then free them all.
int main(void) {
// Allocate resources
// declare and allocate in one step
int* i = malloc(sizeof *i);
double* j = malloc(sizeof *j);
// Test for acceptability
bool ok = i && j;
// Perform the main body of code
if (ok) {
; // do normal process in the code;
}
// free resources
free(i);
free(j);
// return status
return ok ? 0 : -1;
}
int *i=NULL,*j=NULL;
if(!(i=malloc(sizeof(int))))
goto EXIT;
if(!(j=malloc(sizeof(int))))
goto EXIT;
/* do some work */
return 0;
EXIT:
free(i);
free(j);
exit(EXIT_FAILURE);
Although goto is considered a bad programming practice
but here we can use it to get our task done with ease and simplicity

private memory usage keep raising using c in Linux

I'm writing a service in Linux using c, so I need to keep the memory usage stable.
But after tracing a day, the memory raise.
If I monitor from the System Monitor in Linux, it raise 1M and the mem%(0 -> 0.1).
In pmap command, it raise 1M, too.
I have use valgrind to check if there are any memory leak, and it report none if I run once.
If I start the service and use valgrind, it will report that I free invalid pointer.
So, I think it should have something to do about my pointer.
struct list {
int no;
BYTE parm[SLEN];
struct list *next;
};
struct list *memory_current;
struct list *memory_head;
struct list *memory_prev;
int getMemoryUsage(int sendCmd) {
pthread_mutex_lock(&lock);
FILE *fp = NULL;
BYTE buffer[10] = "";
BYTE memorys[10] = "";
int flag = 0;
TRY {
if ((fp = popen("free_data=$(free -m | grep Mem);total=$(echo $free_data | cut -f2 -d' ');"
"free_data=$(free -m | grep 'buffers/cache');buffers=$(echo $free_data | cut -f3 -d' ');echo $(($buffers*100/$total))", "r")) == NULL) {
THROW(CMD_NOT_FND);
}
else {
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
strcat(memorys, buffer);
memory_current = (struct list *)malloc(sizeof(struct list));
if (memory_current == NULL) {
THROW(MALLOC_ERROR);
}
memory_current->next = NULL;
strncpy(memory_current->parm, buffer, SLEN -1);
memory_current->parm[SLEN -1] = '\0';
if (memory_head == NULL)
memory_head = memory_current;
else
memory_prev->next = memory_current;
memory_prev = memory_current;
memset(buffer, 0, sizeof(buffer));
flag = 1;
}
if (flag == 0)
THROW(CMD_NOT_FND);
}
}
CATCH (CMD_NOT_FND) {
memorys[0] = 'n';
memorys[1] = '/';
memorys[2] = 'a';
printf("Memory Usage % : %s\n", memorys);
printLog("Memory Usage % ->", memorys);
}
CATCH (MALLOC_ERROR) {
memorys[0] = 'n';
memorys[1] = '/';
memorys[2] = 'a';
printf("Memory Usage malloc error : %s\n", memorys);
printLog("Memory Usage malloc error ->", memorys);
}
FINALLY {
pclose(fp);
// printf("Memory Usage % : %s\n", memorys);
// printf("Memory Usage length %d\n", strlen(memorys));
}
ETRY;
if (sendCmd == 1) {
if (flag != 0) {
memory_current = memory_head;
int totalMemory = 0;
int count = 0;
int avg = 0;
int perc = 0;
BYTE avg_memory[10] = "";
while (memory_current != NULL) {
sscanf(memory_current->parm, "%d", &perc);
totalMemory += perc;
memory_current = memory_current->next;
count++;
}
avg = totalMemory / count;
snprintf(avg_memory, sizeof(avg_memory), "%d", avg); ;
strcat(avg_memory, ";");
printf("Memory Usage % : %s\n", avg_memory);
printLog("Memory Usage % ->", avg_memory);
// free linked list
memory_current = memory_head;
while (memory_current != NULL) {
memory_prev = memory_current;
memory_current = memory_current->next;
free(memory_prev);
memory_prev = NULL; //fix dangling
}
head_memory = NULL; //fix dangling
current_memory = NULL; //fix dangling
}
}
pthread_mutex_unlock(&lock);
return 0;
}
I have the global pointer to keep record the memory usage in a timer, and I will use the result and clear the list in a interval of time.
I use the same way to use in other function and the memory usage is fine, but the pointers are local and will free at the end.
Could you please help to advice or pointer out what is wrong about my pointer usage.
Thanks.
[Update]
I found that this might be a dangling pointer, so I set the pointer to NULL after the free.
So far the memory won't raise, but I'll keep watching it for more days.
Solved
The memory won't raise again, so I guess it's the dangling pointer issue.
memory_current, memory_head and memory_prev were not initialized to NULL.
you check:
if (memory_head == NULL)
when memory_head was not initialized, therefore you maybe loose some memory allocations
also look like they should be local variables, not global.

Resources