I have created a program based on a linked-list where every node is a struct that holds an 8-byte integer and a pointer to the next node. The queue follows FIFO. It seems to work fine but I suspect the program could suffer from some kind of memory-leak or memory fragmentation in the heap. I may be wrong - hopefully!!! When a node is deleted in FIFO-order I use the library function free where I put the pointer of that node. I also set the pointer to the first and last node to NULL when the linked-list is empty.
But there is a thing that I do not understand and could be sign of a memory-leak.
Let say I create 3 nodes that holds 3 integers. The memoryaddresses of these nodes is as follows:
205888
206032
206056
Now I decide to delete these nodes and free resources to these three nodes.
And when I startover to add nodes - the first node do not start at address 205888, it starts at address 206056.
Does this reveal a memory-leak in my program?
Here is the function the destroy the node. It takes as argument the address to nodes that is to be deleted
static int destroy_node(node *node_ref) {
int data = 0;
data = node_ref->data;
free(node_ref);
return data;
}
and the struct
typedef struct node {
int data;
struct node *next;
} node;
If you free an area of memory, you cannot be sure what will be allocated for you next. So this behaviour basically does not show a memory leak.
There may be a memory leak in your code but you can not detect it using address of the allocated node.
To detect memory leak in your code you need tools like Valgrind
It would depend on the algorithm in the heap. Strictly speaking, this is "indeterminant" and out of your control. It could be a sign, but it's not evidence.
Related
I have some issues, maybe coming from a misunderstanding of how the function "free" works.
Basically I have defined a structure like this
typedef char parola[11]
typedef struct _node node
struct _node
{
parola wrd;
node *padre;
node *Ts;
node *Td;
};
Later in the code I allocate memory for a node using malloc:
node *r
r = (node *) malloc(sizeof(node));
And i create binary search trees allocating memory for every single node in this way.
When I try to remove a node in a bst, I pass a pointer to that node *n. I think I nail the recursive procedure, but then when it comes to using free() on the pointer to the node, that doesn't seem to work. I am sure of it because if I try to print "parola" in the node, it does actually print the word that was contained there after deallocating the memory.
node *n
.../*in another function*/
free (n)
printf("%s\n",n->wrd)
/*This does print the word inside the node after the deallocation*/
What am I missing here? Do i need to use free() in a different way?
Thanks for your help.
In C, free doesn't wipe the data. It just says "I'm not using it any more; you can use it for something else." If nothing needs to use it in that time, it won't be overwritten.
However, you can't guarantee that it won't be overwritten. Using stuff after it's freed is an excellent way to have your program suddenly, unpredictably fail at the worst possible moment.
(Make sure you free the node(s) you're pointing to before you throw away (or free) their last pointer(s), and make sure you only free each thing once!)
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.
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.