I have created a struct, which contains a variable. The struct looks as follows:
typedef struct ABC {
int x;
} ABC;
Now I want to free the whole struct, do I need to free the variable first?
ABC *p = malloc(sizeof(ABC));
p->x = 10;
free(&x); // Is this step needed?
free(p);
p = NULL;
Assuming you meant p->x instead of x...
free(&p->x); // Is this step needed?
Absolutely not. Not only it isn't needed, it's also wrong. You cannot free something that is not a previously allocated pointer. The field x is an integer. Simple as that. In other words, in order to be able to free() something, you would have to allocate it first.
Related
Hello I have a question regarding malloc and free type of things.
suppose I have a structure with another structure inside it
typedef struct All{
int number;
} A;
typedef struct Bet{
A *point;
} B;
Then I create a B.
B* first = malloc(sizeof(B));
first->point=malloc(sizeof(A));
Now lets say I want to make a function that deletes the struct B entirely.
For the delete function I know we have to use
free(first);
So do I also have to free(first->point) or will it disappear automatically if i do free(first);
I want to add more to what #thisisbenmanley said and build an actual explination that will also show how to wrap part of the code you write.
The basics
I'll cover just malloc() and free() here. Whenever you call malloc() there should be a free() also. Let's take this example with a simple int.
int *p = malloc(sizeof(int));
*p = 5;
printf("%d", *p);
free(p);
It is the same for a struct. Another example:
typedef struct Person
{
int Age;
int Height;
}Person;
Person* p = malloc(sizeof(Person));
p->Age = 20;
p->Height = 185;
// do something with it ...
free(p);
Another very important thing you have to know: malloc() can return NULL if the allocation fails. It actually means that there is no space to allocate the block. It is very important to actually check for it. For example:
int* v = malloc(sizeof(int)*999999999);
if (v == NULL)
{
printf("Allocation failed.");
return -1;
}
// Allocation successfull. Do something with the vector ...
Structures in structures and structures with pointers
If structures do not contain pointers just free() will do the job. Example:
typedef struct Point
{
int x;
int y;
}Point;
typedef struct Line
{
Point a;
Point b;
}Line;
// this will allocate actually 4 ints
Line* p = malloc(sizeof(Line));
// this is how you access each point's coordinates.
p->a.x;
// do something ...
// this will free both points (the 4 ints)
free(p);
Now this is where code can get very unclear depending on each situation. If a structure contains one or more pointers if might prove difficult to keep the code simple to read. Suppose the following struct:
typedef struct Person
{
int Age;
int Height;
char* FName;
char* LName;
char* Address;
}Person;
If you want to allocate a Person you need 4 malloc() calls. If you also add error checking it will be quite voluminous. Definetly this should be wrapped inside a function:
Person* AllocPerson()
{
// i'm skipping it now so that my point is clear, but checking
// if malloc returned NULL is recommended
Person* p = malloc(sizeof(Person));
p->FName = malloc(sizeof(char)*30);
p->LName = malloc(sizeof(char)*30);
p->Address = malloc(sizeof(char)*40);
return p;
}
Now whenever you need a Person you can just Person* p = AllocPerson();. Same goes with a FreePerson() function which will take 4 free() calls so that after you finished working with the struct, you simply call FreePerson(p).
void FreePerson(Person* p)
{
free(p->FName);
free(p->LName);
free(p->Address);
free(p);
}
You can evolve the AllocPerson function even further and turn it into a Create function:
Person* CreatePerson(int Age, int Height, char* FirstName, char* LastName, char* Address)
{
// i'm skipping it now so that my point is clear, but checking
// if malloc returned NULL is recommended
Person* p = malloc(sizeof(Person));
p->FName = malloc(sizeof(char)*30);
p->LName = malloc(sizeof(char)*30);
p->Address = malloc(sizeof(char)*40);
p->Age = Age;
p->Height = Height;
strcpy(p->FName, FirstName);
strcpy(p->LName, LastName);
strcpy(p->Address, Address);
return p;
}
Now you can just do this whenever you need a person:
Person* p = CreatePerson(20, 180, "Alex", "Boris", "Street nr. 5");
The CreatePerson() function both allocates and initialises fields of a Person instance. This aproach of making a Create and Delete function to a structure is widely used in C, especially when you have to use an already made API.
Important notes
Always free() memory even though after exiting main() your OS will take care of the blocks still allocated. This is considered good practice.
Try to use dynamic memory as less as possible. The Heap is slower than the Stack!
Try to reuse allocated space whenever possible. Allocating and Freeing are expensive operations!
You would also have to free(first->point). When you free(first), all that will deallocate is the bytes holding the struct first, which only holds a pointer. That alone will not touch the actual memory address pointed to by point; free(first->point) beforehand would cover that.
This is my code:-
typedef struct Frame
{
char* name;
unsigned int duration;
char* path; // may need to scan (with fgets)
}frame_t;
typedef struct Link
{
frame_t* frame;
struct Link* next;
}link_t;
void addNewFrame(void)
{
link_t* newLink = (link_t**)malloc(sizeof(link_t*));
printf(" *** Creating new frame ***\n\n");
printf("Please insert frame path:\n");
// newLink->frame->name = (char*)malloc(sizeof(char) * MAX_LEN);
fgets(newLink->frame->name, MAX_LEN,stdin);
printf("%s", newLink->frame->name);
}
I just need to add a data to name variable in the "Frame" link list, please help me by reviewing this code.
You want to allocate the right types here:-
link_t* newLink = malloc(sizeof(link_t)); //Pointer to Link st
if(newLink){
newLink->frame = malloc(sizeof(frame_t)); //Pointer to frame member
if(newLink->frame){
newLink->frame->name = malloc(sizeof(char) * MAX_LEN); //Pointer to name member
if(newLink->frame->name){
//Rest of your code
}
}
}
EDIT:-
1. As pointed out in comments there's no need to cast the pointer returned by malloc()
2. Another very imp point you may want to check validity of the pointers before de-referencing them
First. You don't need to cast void * so (link_t **)malloc(... can be only malloc(....
Second. You allocated enough memory for a pointer not for a struct. I think you mean malloc(sizeof(link_t)) or even better malloc(sizeof(*newLink))
Third newLink->frame is a pointer so you need to allocate data for it too, newLink->frame = malloc(sizeof(frame_t))
Fourth newLink->frame->name is still a pointer so you need to allocate data for it too. newLink->frame->name = malloc(MAX_LEN)
The confusion that you are doing is pretty common. When you say type *something you are allocating a pointer to type in the stack. A pointer needs to point to somewhere else or NULL, or bad things happen. This applies to structures too. If your structure has a pointer member you need to point it to somewhere else. The somewhere else is where the real "type" object resides.
This also applies to arrays. If you say 'int foo[10]' you are allocating ten integers in the stack. If you say int *foo[10] you are allocating ten pointers in the stack. If you say int **foo you are allocating one pointer in the stack. Again all pointers need to be initialized, I mean, they need to point to some valid object, allocated somewhere else in the memory.
I hope this helps.
Some other points.
Always check pointer coming from malloc, if allocation failed you'll receive NULL. Dereferencing NULL will break your program.
Always initialize memory coming from malloc, fill it with zeros or something.
Don't use _t suffix, is POSIX reserved.
I didn't test any of this.
I have declared a structure in my .h file, as such:
struct node{
char* string;
}
I intend this to have created a structure, example, with one member, a character pointer named string.
Now, I figure out how long the string is and malloc an array of appropriate size, taking the input with that.
char* test;
test = (char*) malloc( n * sizeof(char) );
Insofar as I am aware, this has created character pointer test, and has assigned it to point at the head of the array I just malloc'd. I then proceed to assign each array slot to a character that the user has entered, and I read it back out - this all compiles and works appropriately. My problem comes when I try to assign this character pointer to the character pointer in a structure node passed in to this structure, as:
int f1( struct node* new ){
So I try to assign the pointer in the structure to the value of the pointer to the array, like so:
new->string = test;
But I segfault.
To me, this seems like I am assigning a char* to something that expects a char* so this should be working fine...I'm probably missing something stupid, but does anyone have a direction to point me in? Thanks much!
Check your caller of f1() and make sure your parameter is valid.
This will work:
struct node *you = malloc(sizeof(struct node));
if (you)
{
f1(you);
free(you);
}
As will this:
struct node me;
f1(&me);
This will NOT work
struct node *me;
int f1(me);
Some observations to note:
sizeof(char) is one by definition.
Recommended way of calling malloc is one that avoids casts as well as gets sizeof to infer the type from the pointer being allocated. (See below)
Avoid using names such as new for your identifiers (to the extent possible).
Remember to free the string member within node when you are done.
To elaborate #2, see below --
struct MyType *foo;
foo = malloc( n * sizeof *foo ); /* allocate n elements where n > 0 */
For some reason, if you chose foo to be of some other type, the malloc call is one less line for you to worry about. Also, should you forget to include stdlib.h, the compiler will let you know about it.
beginner in C here. Is this legal here? I keep getting status access violation when i run this code:
struct point {
char *x;
char *y;
}
int main()
{
....
struct point *pt;
for (;;)
{
....
pt = process_message(message);
printf("%s",pt->x);
...
}
}
struct point* process_message(char* message)
{
struct point *pt;
pt = malloc(1*sizeof(struct point))
strncpy(pt->x, message, 4);
return pt;
}
EDIT
Hi guys i made some changes...but still getting the access violation. pls advise!
You need to allocate memory for struct point in process_message.
Something like this:
struct point* process_message(char* message)
{
struct point *pt;
pt = malloc(1*sizeof(struct point));
// ... do some processing ...
return pt;
}
Of course, you should free the pointer at some point afterwards.
Also you should return a struct point in process_message or check your type concordance. If you look carefully, you will see you are returning a struct price* but you are expecting (on the calling side) a struct point *.
UPDATE:
Now that question was updated, you will also need to allocate memory for char *x and char *y if you want to do this:
strncpy(pt->x, message, 4);
I would recommend to read a little bit (or a lot) about memory management and pointers in C++. Pointers are not the only way of dealing with data in C Programming Language.
(NO ERROR CHECKING DONE FOR CODE SIMPLICITY)
Your main function is OK. Your problem is in process_message, where you're using a pointer-to-a-struct but not allocating any memory for it, accessing it, then returning it. Declaring a pointer alone does not create the memory to hold the struct. So you should allocate (use malloc for example) the memory for the struct, so that the memory will "exist" after the end of the function. Then you can return the pointer to it as you're doing, and then you would free it in main when you were done with it.
There are possibly better ways to accomplish the goal here given the simple operation you're doing. One is to keep one "scratch" struct local in your main function, and pass its address to process message:
struct point pt;
process_message(message, &pt);
printf("%s", pt.x);
This will "Reuse" the local memory and not require the alloc/free. Notice here that you don't return anything, you just "fill in" the struct in the process function.
Finally, if you're using a modern version of C, you can actually just return the full structure from the function if you want:
struct point process_message(char* message)
{
struct point pt;
... do some processing ...
return pt;
}
And call it like this:
struct point pt = process_message(message);
Remember to allocate memory in the function process_message
pt = malloc (sizeof (struct point));
/* do processing */
return pt;
also after you have finished working with pt remember to free it free (pt).
EDIT
Also you need to allocate the memory blocks to store the strings to x and y in the function, after allocation of the pt. When you have done working, you need to free the strings first (memory blocks) and then the structure.
Whenever you create pointer, it's just a sizeof(ptr) memory , which points to some data. So you must have some memory where your data is stored.
So either allocate memory in your function ( process_message), or in calling function.
it should go like
struct point *pt = (struct point*)malloc(sizeof(struct point));
As written now, you're allocating the struct point, but that structure contains pointers to strings, and not storage for the strings themselves. You need to allocate space for the strings before you copy into them:
pt = malloc(1*sizeof(struct point));
pt->x = (char *)malloc( strlen(message) + 1);
Don't forget to do the same for pt->y before you use it, and don't forget to separately free the storage allocated for the strings, and then that allocated for the struct.
Am unable to run this code...
#include<cstdio>
int main()
{
struct a{
int b;
struct a *next;
};
typedef struct a no;
no *n;
n->b = 12;
n->next = NULL;
n->next->b = 12;
n->next->next = NULL;
printf("%d %d", n->b, n->next->b);
getchar();
return 0;
}
When you say:
no *n;
you get an uninitialised pointer. When you use that pointer, you get undefined behaviour.
You allocated space for a pointer to a structure, but you didn't allocate space for the actual structure. This means that you don't have a memory address for the structure you are using.
In addition, the pointer points to some random memory address because you didn't initialize it. As a result, you could be trying to read and write to memory that doesn't belong to you, which can cause your program or even your system to crash because of the undefined behavior that results.
As #Neil Butterworth said, you get an uninitialised pointer. This mean that this pointer could point to anywhere, thus giving an access violation error. The way to fix this is simple, just call malloc() before using that pointer. malloc() gives that pointer a valid and usable address, so no one will complain about that.
You're declaring a struct INSIDE a function.
Declare the struct OUTSIDE of the function.
The typedef should be declared outside the function too.
#include<cstdio>
struct a{
int b;
struct a *next;
};
typedef struct a no;
int main()
{
///... your code...
}
try something like this:
no *n = (no*)malloc(sizeof(no));
#include <cstdio>
/* declaring the struct in the function definition may be possible (I'm not sure,
actually, haha). Unless you have a GOOD reason, it's good practice to declare
structs, globals, typedefs, etc... outside the function */
typedef struct a{
int b;
struct a *next;
} no;
int main()
{
no *n;
/* Here, you have a pointer. Remember these are simply (generally) 32-bit values
defined in your stack space used to store a memory location which points to your
ACTUAL struct a! Depending on what USED to be in the stack space, this could
point ANYWHERE in memory, but usually you will find that it points to the NULL
memory location, which is just address "0". To get this to point to something,
you have to allocate empty space on your heap to store your struct... */
n = malloc(sizeof(no));
/* Now your pointer n points to an allocated 'struct a', and you can use it like
normal */
n->b = 12;
n->next = NULL;
/* You just set n->next, which is another 'no' pointer, to NULL. This means that
n->next points nowhere. So, just like above you have to malloc another instance
of the struct! */
n->next = malloc(sizeof(no));
/* NOW you can use n->next with no ill effects! */
n->next->b = 12;
n->next->next = NULL;
printf("%d %d", n->b, n->next->b);
getchar();
/* After you're done with your structs, you want to free them using the POINTERS
that reference them */
free(n->next);
free(n);
return 0;
}