If I have a snippit of my program like this:
struct Node *node;
while(...){
node = malloc(100);
//do stuff with node
}
This means that every time I loop through the while loop I newly allocate 100 bytes that is pointed to by the node pointer right?
If this is true, then how do I free up all the memory that I have made with all the loops if I only have a pointer left pointing to the last malloc that happened?
Thanks!
Please allocate exactly the size you need: malloc(sizeof *node); -- if you move to a 64-bit platform that doubles the size of all your members, your old 96-byte structure might take 192 bytes in the new environment.
If you don't have any pointers to any of the struct Nodes you have created, then I don't think you should be allocating them with malloc(3) in the first place. malloc(3) is best if your application requires the data to persist outside the calling scope of the current function. I expect that you could re-write your function like this:
struct Node node;
while(...){
//do stuff with node
}
or
while(...){
struct Node node;
//do stuff with node
}
depending if you want access to the last node (the first version) or not (the second version).
Of course, if you actually need those structures outside this piece of code, then you need to store references to them somewhere. Add them to a global list keeping track of struct Node objects, or add each one to the next pointer of the previous struct Node, or add each one to a corresponding struct User that refers to them, whatever is best for your application.
If you set node = NULL before the loop and then use free(node) before node = malloc(100) you should be OK. You will also need to do a free(node) after the loop exits. But then again, it all depends on what "//do stuff with node" actually does. As others have pointed out, malloc(100) is not a good idea. What I would use is malloc(sizeof(*node)). That way, if the type of node changes, you don't have to change the malloc line.
If you don't need the malloc'ed space at the end of one iteration anymore, you should free it right away.
To keep track of the allocated nodes you could save them in a dynamically growing list:
#include <stdlib.h>
int main() {
int i;
void *node;
int prt_len = 0;
void **ptrs = NULL;
for (i = 0; i < 10; i++) {
node = malloc(100);
ptrs = realloc(ptrs, sizeof(void*) * ++prt_len);
ptrs[prt_len-1] = node;
/* code */
}
for (i = 0; i < prt_len; i++) {
free(ptrs[i]);
}
free(ptrs);
return 0;
}
Note: You should probably re-think your algorithm if you need to employ such methods!
Otherwise see sarnold's answer.
then how do I free up all the memory that I have made with all the loops if I only have a pointer left pointing to the last malloc that happened?
You can't. You just created a giant memory leak.
You have to keep track of every chunk of memory you malloc() and free() it when you're done using it.
You can not. You need to store all the pointer to free the memory. if you are saving those pointer somewhere then only you can free the memory.
Related
My data gets overwritten whenever I insert a new value ,If I omit my free() in the main program my program works fine.Why ?How to recify this issue.Is memory allocation of structure is correct?
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct List
{
char val[20] ;
};
struct Hashtable
{
struct List *start;
};
struct Hashtable ht[26];
void init();
void insert(struct List*);
void init()
{
register int j;
for (j=0;j<26;j++)
{
ht[j].start=NULL;
}
}
int main(void)
{
init();
int i=0;
for (int i=0;i<5;i++)
{
struct List *newnode=(struct List*)malloc(sizeof(struct List));
scanf("%s",newnode->val);
insert(newnode);
free(newnode);
newnode=NULL;
}
return 0;
}
void insert(struct List *node)
{
if ( ht[node->val[0]-97].start==NULL)
{
ht[node->val[0]-97].start=node;
return;
}
else
{
printf("The value is %s\n", ht[node->val[0]-97].start->val);
}
}
-------------------------------------------------------------------------------------------------------------------------------------------------___________________________________________________________________________
When you assign pointers, you only copy the pointers themselves, not the memory they might point to.
When you call free using a pointer, all copies of that pointer become invalid and can no longer be used.
You either need to make a completely new copy in the insert function (including allocating a new List structure), or you should not call free.
My personal recommendation is that you don't allocate at all in the main function, and that the insert function takes the string to "insert" as an argument (instead of the List pointer it currently takes).
Perhaps something like this:
void insert(char *val)
{
// Get the hash-table index (note that it only works with ASCII encoding)
char hash = tolower(val[0]) - 'a';
// First check if it exists
if (ht[hash].start == NULL)
{
// No, then add it
// First allocate memory for the node
struct List *node = malloc(sizeof *node);
// Then copy the string
strcpy(node->val, val);
// And finally add it
ht[hash].start = node;
}
}
Then your loop in the main function could be like
for (unsigned i = 0; i < 5; ++i)
{
char val[20];
scanf("%19s", val);
insert(val);
}
Imagine memory is a row of lockers, each containig an 8 bit value, and numbered as 1, 2, 3... (Well, higher values usually, but you get it). A pointer is just the number of that locker, nothing more. What malloc does, is:
Find a spot with free memory
Mark that memory as used
Return the number of the first locker
When you free, you mark again that memory as free. There are many algorithms to do this, but it would be wise to search for a small free memory space whith its number as low as possible, since leaving empty spaces is a waste of memory.
When you assign a pointer, you do not assign the values it points to, but the locker number.
When you free, you give the algorithm the possibility to use that locker, and when you use malloc again, it probably finds the same locker as before, and then you modify its contents.
Remember that your hashtable still uses that locker number, and when it opens the locker, it will find out its contents are modified.
Solution below:
TL;DR:
Your hash table uses still the same memory, so don't free it, since it might be modified when found by malloc.
Free it from the hashtable once you are finished using that pointer, to avoid wasting memory
Note: If you just read the solution, understanding heap (above), will help you with a lot of headaches, plus it is nice to know what the computer is doing with your code.
I'm studying linked lists from this lesson.
The writer (and all other coders on every single tutorial) goes through creating node type pointer variables, then allocates memory to them using typecasting and malloc. It seems kinda unnecessary to me (Offourse I know I'm missing something), why can't we implement the same using this?
struct node
{
int data;
struct node *next;
};
int main()
{
struct node head;
struct node second;
struct node third;
head.data = 1;
head.next = &second;
second.data = 2;
second.next = &third;
third.data = 3;
third.next = NULL;
getchar();
return 0;
}
I've created nodes and the next pointers points towards the addresses of the next nodes...
Let's say you create a variable of type node called my_node:
struct node my_node;
You can access its members as my_node.data and my_node.next because it is not a pointer. Your code, however, will only be able to create 3 nodes. Let's say you have a loop that asks the user for a number and stores that number in the linked list, stopping only when the user types in 0. You don't know when the user will type in 0, so you have to have a way of creating variables while the program is running. "Creating a variable" at runtime is called dynamic memory allocation and is done by calling malloc, which always returns a pointer. Don't forget to free the dynamically allocated data after it is no longer needed, to do so call the free function with the pointer returned by malloc. The tutorial you mentioned is just explaining the fundamental concepts of linked lists, in an actual program you're not going to limit yourself to a fixed number of nodes but will instead make the linked list resizable depending on information you only have at runtime (unless a fixed-sized linked list is all you need).
Edit:
"Creating a variable at runtime" was just a highly simplified way of explaining the need for pointers. When you call malloc, it allocates memory on the heap and gives you an address, which you must store in a pointer.
int var = 5;
int * ptr = &var;
In this case, ptr is a variable (it was declared in all its glory) that holds the address of another variable, and so it is called a pointer. Now consider an excerpt from the tutorial you mentioned:
struct node* head = NULL;
head = (struct node*)malloc(sizeof(struct node));
In this case, the variable head will point to data allocated on the heap at runtime.
If you keep allocating nodes on the heap and assigning the returned address to the next member of the last node in the linked list, you will be able to iterate over the linked list simply by writing pointer_to_node = pointer_to_node->next. Example:
struct node * my_node = head; // my_node points to the first node in the linked list
while (true)
{
printf("%d\n", my_node->data); // print the data of the node we're iterating over
my_node = my_node->next; // advance the my_node pointer to the next node
if (my_node->next == NULL) // let's assume that the 'next' member of the last node is always set to NULL
{
printf("%d\n", my_node->data);
break;
}
}
You can, of course, insert an element into any position of the linked list, not just at the end as I mentioned above. Note though that the only node you ever have a name for is head, all the others are accessed through pointers because you can't possibly name all nodes your program will ever have a hold of.
When you declare 'struct node xyz;' in a function, it exists only so long as that function exists. If you add it to a linked list and then exit the function, that object no longer exists, but the linked list still has a reference to it. On the other hand, if you allocate it from the heap and add it to the linked list, it will still exist until it is removed from the linked list and deleted.
This mechanism allows an arbitrary number of nodes to be created at various times throughout your program and inserted into the linked list. The method you show above only allows a fixed number of specific items to be placed in the list for a short duration. You can do that, but it serves little purpose, since you could have just accessed the items directly outside the list.
Of course you can do like that. but how far ? how many nodes are you going to create ? We use linkedlists when we don't know how many entries we need when we create the list. So how can you create nodes ? How much ?
That's why we use malloc() (or new nodes).
But what if you had a file containing an unknown number of entries, and you needed to iterate over them, adding each one to the linked list? Think about how you might do that without malloc.
You would have a loop, and in each iteration you need to create a completely new "instance" of a node, different to all the other nodes. If you just had a bunch of locals, each loop iteration they would still be the same locals.
Your code and approach is correct as long as you know the number of nodes that you need in advance. In many cases, though, the number of nodes depends on user input and is not known in advance.
You definitely have to decide between C and C++, because typecasting and malloc belong in C only. Your C++ linked list code won't be doing typecasting nor using malloc precisely because it's not C code, but C++ code.
Say you are writing an application such as a text editor. The writer of the application has no idea how big a file a user in the future may want to edit.
Making the editor always use a large amount of memory is not helpful in multi-tasking environments, especially one with a large number of users.
With malloc() an editing application can take additional amounts of memory from the heap as required, with different processes using different amounts of memory, without large amounts of memory being wasted.
You can, and you can exploit this technique to create cute code like this, to use the stack as a malloc in a way:
The code below should be safe enough assuming there are no tail optimizations enabled.
#include <stdio.h>
typedef struct node_t {
struct node_t *next;
int cur;
int n;
} node_t;
void factorial(node_t *state, void (*then)(node_t *))
{
node_t tmp;
if (state->n <= 1) {
then(state);
} else {
tmp.next = state;
tmp.cur = state->n * state->cur;
tmp.n = state->n - 1;
printf("down: %x %d %d.\n", tmp);
factorial(&tmp, then);
printf("up: %x %d %d.\n", tmp);
}
}
void andThen(node_t *result)
{
while (result != (node_t *)0) {
printf("printing: %x %d %d.\n", *result);
result = result->next;
}
}
int main(int argc, char **argv)
{
node_t initial_state;
node_t *result_state;
initial_state.next = (node_t *)0;
initial_state.n = 6; // factorial of
initial_state.cur = 1; // identity for factorial
factorial(&initial_state, andThen);
}
result:
$ ./fact
down: 28ff34 6 5.
down: 28ff04 30 4.
down: 28fed4 120 3.
down: 28fea4 360 2.
down: 28fe74 720 1.
printing: 28fe74 720 1.
printing: 28fea4 360 2.
printing: 28fed4 120 3.
printing: 28ff04 30 4.
printing: 28ff34 6 5.
printing: 0 1 6.
up: 28fe74 720 1.
up: 28fea4 360 2.
up: 28fed4 120 3.
up: 28ff04 30 4.
up: 28ff34 6 5.
factorial works differently than usual because we can't return the result to caller because the caller will invalidate it with any single stack operation. a single function call will destroy the result, so instead, we must pass it to another function that will have its own frame on top of the current result, which will not invalidate the arbitrary number of stack frames it's sitting on top of that hold our nodes.
I imagine there are many ways for this to break other than tail call optimizations, but it's really elegant when it doesn't, because the links are guaranteed to be fairly cache local, since they are fairly close to each other, and there is no malloc/free needed for arbitrary sized consecutive allocations, since everything is cleaned as soon as returns happen.
Lets think you are making an Application like CHROME web browser, then you wanna create link between tabs created by user at run time which can only possible if you use Dynamic Memory Allocation.
That's why we use new, malloc() etc to apply dynamic memory allocation.
☺:).
consider the following structures:
struct intNode
{
int num;
intNode* pNext;
};
struct list
{
intNode* first;
intNode* last;
int size;
};
suppose I allocated memory for the list. If I call free(lst) will it also free the memory allocated to the intNode first and last? and what about their own pNext? Intuitively I feel like I need to recursively free the nested memory blocks from the inside out.
You need to free them all individually, but usually for linked lists this is done iteratively, not recursively:
void DeleteList(struct intNode *pHead)
{
struct intNode *pCur=pHead, *pDel=NULL;
while(pCur != NULL)
{
pDel = pCur;
pCur = pCur->pNext;
free(pDel);
}
}
If you only frees memory of list element (when you have nodes), you cause a memory leak. In memory, the list looks like this:
[list caption]...other data...[node]...other data...[node]...[last node]
^(It is not always first!)
So, nodes aren't one uninterrupted memory area and they are not in contact with the caption. In these elements you have only address of next node, therefore you must free them memory of each element separately. If you do it only with the caption, the nodes remain in the memory. Furthermore you'll lose the address of first node, thereby you'll lose all addresses of all elements! In this case, you will not be able to get to the nodes or free their memory.
In response to your question, yes, you should do more. Freeing "parent's" memory isn't enough. In general, you should use free as much times as you use malloc or calloc. In this case it is simple. I just need to get the address of the first node and sequentially purified memory. Do not forget to keep the address of the next node (in a variable) before removing recent.
Having the following,
struct node{
int value;
struct node *next;
};
typedef struct node Node;
typedef struct node *pNode;
Node newNode(){
Node n;
n.value = 5;
return n;
}
pNode newpNode(){
pNode pn = (pNode) malloc(sizeof(Node));
pn->value = 6;
return pn;
}
I read somewhere that if memory deallocation is to be done by the caller function, I should use newpNode(), and otherwise use newNode(), but that does not help me understand quite enough.
Can you give me some concrete examples of when should I use newNode() and when newpNode()?
Edit: forgot pn inside newpNode()
In this simple example, there is no strong need to use one over the other.
When you call newNode(), memory is allocated when the function is called to store the size of a Node to be returned from the call (on the call stack). This memory can be assigned to a variable and you will keep it around (the memory on the call stack will be memcpy'd into your local variable):
Node n = newNode();
However, as a Node gets more complicated, you will run into problems. For example, if you have nested data structures, these won't get copied along and could be destroyed as newNode() cleans up.
Also, as the memory required for Node gets larger (i.e. more fields), it will take more and more memory on the stack to make these calls. This can limit things such as recursion, or just general efficiency.
To deal with these limitations, you allocate memory on the heap in newPNode(); This always returns a pointer, regardless of the size of Node. However, you have to make sure you explicitly clean up this memory later, or you will have a memory leak.
I'm just reading about malloc() in C.
The Wikipedia article provides an example, however it justs allocate enough memory for an array of 10 ints in comparison with int array[10]. Not very useful.
When would you decided to use malloc() over C handling the memory for you?
Dynamic data structures (lists, trees, etc.) use malloc to allocate their nodes on the heap. For example:
/* A singly-linked list node, holding data and pointer to next node */
struct slnode_t
{
struct slnode_t* next;
int data;
};
typedef struct slnode_t slnode;
/* Allocate a new node with the given data and next pointer */
slnode* sl_new_node(int data, slnode* next)
{
slnode* node = malloc(sizeof *node);
node->data = data;
node->next = next;
return node;
}
/* Insert the given data at the front of the list specified by a
** pointer to the head node
*/
void sl_insert_front(slnode** head, int data)
{
slnode* node = sl_new_node(data, *head);
*head = node;
}
Consider how new data is added to the list with sl_insert_front. You need to create a node that will hold the data and the pointer to the next node in the list. Where are you going to create it?
Maybe on the stack! - NO - where will that stack space be allocated? In which function? What happens to it when the function exits?
Maybe in static memory! - NO - you'll then have to know in advance how many list nodes you have because static memory is pre-allocated when the program loads.
On the heap? YES - because there you have all the required flexibility.
malloc is used in C to allocate stuff on the heap - memory space that can grow and shrink dynamically at runtime, and the ownership of which is completely under the programmer's control. There are many more examples where this is useful, but the one I'm showing here is a representative one. Eventually, in complex C programs you'll find that most of the program's data is on the heap, accessible through pointers. A correct program always knows which pointer "owns" the data and will carefully clean-up the allocated memory when it's no longer needed.
What if you don't know the size of the array when you write your program ?
As an example, we could imagine you want to load an image. At first you don't know its size, so you will have to read the size from the file, allocate a buffer with this size and then read the file in that buffer. Obviously you could not have use a static size array.
EDIT:
Another point is: When you use dynamic allocation, memory is allocated on the heap while arrays are allocated on the stack. This is quite important when you are programming on embedded device as stack can have a limited size compared to heap.
I recommend that you google Stack and Heap.
int* heapArray = (int*)malloc(10 * sizeof(int));
int stackArray[10];
Both are very similar in the way you access the data. They are very different in the way that the data is stored behind the scenes. The heapArray is allocated on the heap and is only deallocted when the application dies, or when free(heapArray) is called. The stackArray is allocated on the stack and is deallocated when the stack unwinds.
In the example you described int array[10] goes away when you leave your stack frame. If you would like the used memory to persist beyond local scope you have to use malloc();
Although you can do variable length arrays as of C99, there's still no decent substitute for the more dynamic data structures. A classic example is the linked list. To get an arbitrary size, you use malloc to allocate each node so that you can insert and delete without massive memory copying, as would be the case with a variable length array.
For example, an arbitrarily sized stack using a simple linked list:
#include <stdio.h>
#include <stdlib.h>
typedef struct sNode {
int payLoad;
struct sNode *next;
} tNode;
void stkPush (tNode **stk, int val) {
tNode *newNode = malloc (sizeof (tNode));
if (newNode == NULL) return;
newNode->payLoad = val;
newNode->next = *stk;
*stk = newNode;
}
int stkPop (tNode **stk) {
tNode *oldNode;
int val;
if (*stk == NULL) return 0;
oldNode = *stk;
*stk = oldNode->next;
val = oldNode->payLoad;
free (oldNode);
return val;
}
int main (void) {
tNode *top = NULL;
stkPush (&top, 42);
printf ("%d\n", stkPop (&top));
return 0;
}
Now, it's possible to do this with variable length arrays but, like writing an operating system in COBOL, there are better ways to do it.
malloc() is used whenever:
You need dynamic memory allocation
If you need to create array of size n, where n is calculated during your program execution, the only way you can do it is using malloc().
You need to allocate memory in heap
Variables defined in some functions live only till the end of this function. So, if some "callstack-independent" data is needed, it must be either passed/returned as function parameter (which is not always suitable), or stored in heap. The only way to store data in heap is to use malloc(). There are variable-size arrays, but they are allocated on stack.