Why only one free() works for this segment of code? - c

I use free() to free the structure I allocated before, and I want to test if they have successfully free, but I get only one of them free why?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct student{
char *name;
struct student *next;
}student;
int main(int argc, const char * argv[]) {
student *a=malloc(sizeof(student));
a->name="echo";
student *b=malloc(sizeof(student));
b->name="harry";
a->next=b;
b->next=NULL;
free(a);
free(b);
printf("%s\n", a->name);
printf("%s\n", b->name);
return 0;
}
and I got this output.Why?
(null)
harry
Program ended with exit code: 0

You can't "test" if they have successfully been freed, trying to access any memory that has been freed is undefined behavior, instead of testing just accept and move on.

You have freed the memory but that doesn't mean the pointer has been invalidated by the system. In your second case, the data where it pointed to has not yet been re-used so printf finds it and can print.
In the first case the memory has been re-used or reset. print finds a null pointer.
In the second case the memory has not yet been re-used: printf finds it and can print it.
But this undefined behavior and anything could have happened.

You can better use free along with setting the variable to NULL.
free(b);
b = NULL;
free(a);
a = NULL;
When you call free, the variable is marked for recollection. And when that recollection of the memory allocated should happen is up to the underlying OS. You should not access the freed block.

Related

munmap_chunk(): invalid pointer, when to use free()

I'm curious as to why free(myWord->w) would be an invalid pointer? I allocate memory to it, so shouldn't I free it as well? or does freeing a struct also free all of its fields?
New to C so any insight on the world of pointers is much appreciated!
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct word {
char *w;
} WORD;
void setWord(char **f);
int main() {
WORD *myWord = malloc(sizeof(WORD));
myWord->w = malloc(6);
strcpy(myWord->w, "hello"); // set to "hello"
setWord(&(myWord->w)); // set to "bagel"
free(myWord->w); /* munmap_chunk(): invalid pointer. Aborted (core dumped) */
free(myWord);
return 0;
}
void setWord(char **F) {
*F = "bagel";
}
*F = "bagel"; is not how you assign a string. Instead the code overwrite the value of the pointer myWord->w so when you call free, it's no longer the correct pointer value.
To see that the pointer change, try this:
printf("%p\n", (void*)myWord->w);
setWord(&(myWord->w)); // set to "bagel"
printf("%p\n", (void*)myWord->w);
Consequently, the free call will fail as the pointer-value isn't the one you got from the malloc.
So instead of *F = "bagel"; use
strcpy(*F, "bagel"); // NOT: *F = "bagel"
Further you don't need to pass the address of w. Simply do:
void setWord(char *F) {
strcpy(F, "bagel");
}
and call it like:
setWord(myWord->w);
And...
I allocate memory to it, so shouldn't I free it as well? or does freeing a struct also free all of its fields?
Yes, you must free it.
No, free of a struct does not free members automatically. You must do that.

Problems with pointer into structure

The memory has not been freeded
Please some help with this problem
#include <stdio.h>
#include <stdlib.h>
typedef struct paramint
{
short val;
char name[150 + 1];
}tParamint;
int main(int argc, char *argv[]) {
tParamint *e;
e=(tParamint*)malloc(2*sizeof(tParamint));
e[1].val=12;
e[2].val=13;
printf("e[1].val=[%d]\n", e[1].val);
printf("e[2].val=[%d]\n", e[2].val);
free(e);
printf("e[1].val=[%d]\n", e[1].val);
printf("e[2].val=[%d]\n", e[2].val);
return 0;
}
Initial value:
e[1].val=[12]
e[2].val=[13]
After free
e[1].val=[12]
e[2].val=[13]
From the reference
There are two points
A block of memory previously allocated by a call to malloc, calloc or realloc is deallocated, making it available again for further allocations.
Notice that this function does not change the value of ptr itself, hence it still points to the same (now invalid) location.
So the memory you just freed, are not deallocated immediately, it just marked as re-allocatable and your ptr is pointing to those invalid location. So it's a good idea to de-referencing the ptr to null just after freeing the ptr.
By de-referencing the ptr to null after you also make sure that, you are not freeing the same memory more than once.

Will freeing a structure pointer also free the memory allocated inside of the structure in C?

For example I have this structure:
typedef struct{
char *var = (char*)malloc(20*sizeof(char));
} EXAMPLE;
EXAMPLE *point = (EXAMPLE*)malloc(sizeof(EXAMPLE));
My first question is, will the memory allocated inside the structure only be allocated when I allocate memory for the EXAMPLE pointer?
My second question, when I use free(point) will the memory allocated for var also be freed?
With this struct:
typedef struct{
char *var;
} EXAMPLE;
Remember that when you allocate space for the struct, you're allocating space only for the char * pointer. This pointer just points to memory elsewhere. When you free() the struct, you're just freeing the char * pointer, not the actual memory that it points to.
As such, if you make this struct and then malloc() space for the string you want var to point to, you need to free() the string as well as free()ing the struct.
Some code demonstrating how this might work:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct {
char *var;
} EXAMPLE;
int main(int argc, char *argv[]) {
// malloc() space for the EXAMPLE struct.
EXAMPLE *point = malloc(sizeof(EXAMPLE));
// malloc() space for the string that var points to.
point->var = malloc(20 * sizeof(char));
// Copy "Hello!" into this memory (care with strcpy).
strcpy(point->var, "Hello!");
// Print it, it works!
printf("point->var is: %s\n", point->var);
// Free stuff.
free(point->var);
free(point);
return 0;
}
Also note that we don't cast the result of malloc(), in C you're not meant to. Also note that we free() point->var first before point. This is important because if we free() point first, we lose the pointer to point->var, and we have a memory leak.
I'm ignoring the non-compiling code since the question is pretty clear without it ;-)
No. free() does not know the structure of what it is pointing at,so it just frees one "block". If that block has pointers to other malloced memory then they are leaked (unless there is a pointer to those blocks somewhere else).

how to free memory in C

I'm writing a C program but i'm getting some memory errors so i decided to make a small program to see when and how to deallocate memory.
My example :
int main() {
char *a=malloc(5);
a="mama";
char *b=malloc(strlen(a));
printf("%s\n",a);
strcpy(b,a);
free(a);
printf("%s\n",b);
return 0;
}
here i'm getting an error :
* Error in `./a': free(): invalid pointer: 0x0000000000400757 *
but when i change just one line :
int main() {
char *a=malloc(5);
strcpy(a,"mama");
char *b=malloc(strlen(a));
printf("%s\n",a);
strcpy(b,a);
free(a);
printf("%s\n",b);
return 0;
}
My second program is working well, so why i'm getting this error in the first?
i hope that you can explain me why.
In My Real program I'm doing like that :
char * getDate(){
char *date=malloc(5);
//some instructions here
return date;
}
int main() {
char *a=malloc(5);//im sure that a will not exceed 5 bytes
a=getDate();
return 0;
}
It's just a small example , and i don't know where to free memory .so how and where i can free memory , have I to free date or the char pointer?
Edited second Time:
void getDate(char *a){
//some instructions here
strcpy(a,"haha");
}
int main() {
char *a=malloc(5);
getDate(a);
int i= strlen(a);
printf("%s and the size is :%d\n",a,i);
free(a);
return 0;
}
what are the rules i have to follow to avoid memory errors.
many thanks.
In the line:
char *a=malloc(5);
You assign a with the address of a dynamically allocated memory block, but then in the line:
a="mama";
You reassign it with the address of the literal string constant "mama". Discarding the pointer to the dynamically allocated block so that when you call
free(a);
a is no longer a valid heap memory block, and cannot be deallocated.
Strings (and arrays in general) in C are not data first-class types and cannot be assigned. You should replace:
a="mama";
with
strcpy( a, "mama" ) ;
The assignment sets the pointer value - it does not copy "mama" to the memory points to by a. The strcpy() call on teh other hand copies the string to the dynamic memory block referenced by a.
In your second code fragment, you are "leaking" the memory allocated in main() since you have reassigned a without freeing the original block. Although in your example you have not free'd a, it remains freeable, because the allocation in GetDate() is dynamic. As a coding style, dynamically allocating memory in a function and returning its pointer is a bad idea since it makes it the responsibility of the caller to know that the memory was dynamically allocated and must be free'd, and it invites memory leaks.

Memory allocation with malloc?

Below is the snippet of the code:
int main(void) {
char sizing[] = "manshcanshcnams cndhan sndhcna snshans";
char *xyz = malloc(sizeof(char));
printf("%ld\n",sizeof(xyz));
xyz = sizing; // IT SHOULD FAIL HERE
printf("Fail %s\n",xyz );
return 0;
}
As you can see that I am trying to assign more memory to xyz then what it can hold. But the output doesn't fail. Is it an undefined behaviour?
You can't copy strings with =. xyz = sizing just modifies the variable xyz so that it points to the array sizing, instead of pointing to the memory you malloced.
So, your memory is leaked but there is no undefined behavior (except that you forgot to include <stdio.h> and <stdlib.h>).
All you're doing is telling the pointer xyz to point at the memory address associated with sizing. There is no reason that this would fail.
My understanding is that malloc() should not fail unless it cannot allocate the amount of memory it was asked for. However, when you use it, you are required to release that memory when you don't need it anymore or else your program will request more and more memory and eventually the request will fail because you haven't released anything.
Also, not all illegal memory operations cause an error, for example (code edited 2013-03-08 based on Kludas's observation that the previous version wouldn't compile):
#include <stdio.h>
#include <string.h>
int main(void)
{
char myString[4];
strcpy(myString, "abcdefghijklmnopqrstuvwxyz"); /* This overflows the buffer */
/* but MIGHT NOT cause an */
/* immediate crash! */
printf("myString = [%s]\n", myString);
return 0;
}
This may-or-may-not trigger an error, but it is certainly illegal because I am writing 26 characters into an array that should only hold 4 items (three characters plus a terminating NULL).

Resources