I am trying to define a simple linked list
#include <stdio.h>
struct node{
int value;
struct node* next;
};
typedef struct {
struct node* root;
} ll;
void add_to_ll(int value, ll* linked_list) {
struct node new_node = {value, linked_list->root};
linked_list->root = &new_node;
}
void print_ll(ll* ll2) {
printf("%p", ll2);
struct node* temp = ll2->root;
while (temp->next != NULL) {
printf("%d ", temp->value);
temp = temp->next;
}
}
int main()
{
printf("Creating a linked list...\n");
struct node root_node = {1, NULL};
ll my_linked_list = { &root_node };
for (int i = 0; i < 10000; i++) {
add_to_ll(i, &my_linked_list);
}
printf("my_linked_list root value %d\n", my_linked_list.root->value);
printf("my_linked_list root value %d\n", my_linked_list.root->value);
printf("my_linked_list root value %d\n", my_linked_list.root->value);
return 0;
}
The output I am getting is:
Creating a linked list...
my_linked_list root value 9999
my_linked_list root value 429391991
my_linked_list root value 429391991
I am able to get the value of the root node correctly the first time. But on trying to read it the second time (and thereafter) the value changes. What am I missing?
Your problem is with the memory allocation strategy in add.
void add_to_ll(int value, ll* linked_list) {
struct node new_node = {value, linked_list->root};
linked_list->root = &new_node;
}
Here you're instatiating new_node as a local variable. Non-static local variables have a lifespan equal to that of their block. After you exit the block, that memory (which is actually the stack) is available for successive allocations that will overwrite your object. Use explicit allocation, that means malloc, to have objects whose lifespan is independent from the scope of allocation.
I would also point out the naming... The most explicit name should be that of the type, not the variable. So struct linked_list ll and not the other way around.
This function:
void add_to_ll(int value, ll* linked_list) {
struct node new_node = {value, linked_list->root};
linked_list->root = &new_node;
}
Constructs a node on the stack and adds it to the list.
When you return from this function the stack is popped and the list root points to unallocated memory on the stack that will later be reused.
Related
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define SIZE 10
// A hashtable is a mixture of a linked list and array
typedef struct node NODE;
struct node{
int value;
NODE* next;
};
int hash(int);
void insert(int,NODE **);
int main(){
NODE* hashtable[SIZE];
insert(12,&hashtable[SIZE]);
printf("%d\n",hashtable[5]->value);
}
int hash(int data){
return data%7;
}
void insert(int value,NODE **table){
int loc = hash(value);
NODE* temp = malloc(sizeof(NODE));
temp->next = NULL;
temp->value = value;
*table[loc] = *temp;
printf("%d\n",table[loc]->value);
}
The above code prints :
12 and
27475674 (A random number probably the location.)
how do I get it to print 12 and 12 i.e. how to make a change in the array. I want to fill array[5] with the location of a node created to store a value.
The expression *table[loc] is equal to *(table[loc]) which might not be what you want, since then you will dereference an uninitialized pointer.
Then the assignment copies the contents of *temp into some seemingly random memory.
You then discard the memory you just allocated leading to a memory leak.
There's also no attempt to make a linked list of the hash-bucket.
Try instead to initially create the hashtable array in the main function with initialization to make all pointers to NULL:
NODE* hashtable[SIZE] = { NULL }; // Will initialize all elements to NULL
Then when inserting the node, actually link it into the bucket-list:
temp->next = table[loc];
table[loc] = temp;
This is just a simple change which I have made to your program which will tell you what you are actually doing wrong.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define SIZE 10
// A hashtable is a mixture of a linked list and array
typedef struct node NODE;
struct node {
int value;
NODE* next;
};
NODE *hashtable[SIZE] = { NULL };
int hash(int);
int insert(int); //, NODE **);
int main(void)
{
int loc = insert(12); //, &hashtable[SIZE]);
if (loc < SIZE) {
if (hashtable[loc]) {
printf("%d\n", hashtable[loc]->value);
} else {
printf("err: invalid pointer received\n");
}
}
return 0;
}
int hash(int data)
{
return data%7;
}
int insert(int value) //, NODE *table[])
{
int loc = hash(value);
printf("loc = %d\n", loc);
if (loc < SIZE) {
NODE *temp = (NODE *) malloc(sizeof(NODE));
temp->value = value;
temp->next = NULL;
hashtable[loc] = temp;
printf("%d\n", hashtable[loc]->value);
}
return loc;
}
Here I have declared the hashtable globally just to make sure that, the value which you are trying to update is visible to both the functions. And that's the problem in your code. Whatever new address you are allocating for temp is having address 'x', however you are trying to access invalid address from your main function. I just wanted to give you hint. Hope this helps you. Enjoy!
I am studying the following C code:
typedef struct msg *m_;
struct msg
{
long from;
long to;
m_ link;
};
m_ queue;
I would like to see an example that explains the role of the pointer, i.e. m_, of the structure inside the structure itself m_ link!
Thank you very much.
To be pedantic: link is a pointer. m_ is not a pointer, it's a typedef. It is used to avoid the need to say "struct msg* link;" inside the struct definition.
As answered in the comment above, the queue is represented by a pointer to the first item, which has a pointer to the second (if any), and so on until you reach a NULL pointer.
It's important to take care when building such lists that no node points to itself or to any precursor, or you get an infinite loop chasing to the tail.
Pointers to the structure type inside the structure itself are very often used for linked lists, trees, etc. In your example, it is referring to a queue implementation.
Here is a very minimal example of a stack implementation using a linked list. The functions require the address of a stack pointer, and an empty stack is a NULL pointer.
struct linked_stack
{
int data;
struct linked_stack *next;
};
void linked_stack_push(linked_stack **stck, int data)
{
struct linked_stack *node = malloc(sizeof(struct linked_stack));
if (node != NULL)
{
node->data = data;
node->next = *stck;
}
*stck = node;
}
int linked_stack_top(linked_stack **stck)
{
if (*stck != NULL)
return (*stck)->data;
return 0; /* stack is empty */
}
void linked_stack_pop(linked_stack **stck)
{
struct linked_stack *node = *stck;
if (*stck != NULL)
{
*stck = node->next;
free(node);
}
}
Example usage:
int main(void)
{
struct linked_stack *stack = NULL;
linked_stack_push(&stack, 10);
printf("top of stack = %d\n", linked_stack_top(&stack));
linked_stack_pop(&stack);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
struct nodeTree {
int data;
struct nodeTree* left;
struct nodeTree* right;
};
struct nodeTree* insertRoot(struct nodeTree** root, int data) {
if(!(*root)) {
struct nodeTree *temp = malloc(sizeof(struct nodeTree));
if(!temp) {
exit(-1);
}
temp->data = data;
temp->left = 0;
temp->right = 0;
(*root) = temp;
free(temp);
return *root;
}
}
int main() {
struct nodeTree *root = NULL;
root = insertRoot(&root,10);
printf("%d\n",root->data);
return 0;
}
I wrote a function to insert a value in the root of a binary tree. In my insert function I assign a temp node and after inserting the value into the temp node I assign the temp node to root and free the temp node. I understand I can directly malloc into the root variable and assign the data to it. What happens when free(temp) is called and how does it affect the root variable ?
You should not free() temp, because you still point to it with root, they point to the same data, hence freeing temp does free *root too.
As to why it's printing 0 it's just a coincidence, because having free()ed root in the function where you allocated it, and accessing it in main() invokes undefined behavior, a consequence might be that printf() prints, 0, which is a behavior, and since it's undefined, any other behavior is actually possible.
I'm writing a simple linked list implementation for the sake of learning. My linked list consists of node structures that contain an int value and a pointer to the next node. When I run my code, it loops endlessly even though it should terminate when it reaches a NULL pointer. What am I doing wrong?
#include <stdio.h>
struct node {
int value;
struct node *next_node;
};
struct node * add_node(struct node *parent, int value)
{
struct node child;
child.value = value;
child.next_node = NULL;
parent->next_node = &child;
return parent->next_node;
}
void print_all(struct node *root)
{
struct node *current = root;
while (current != NULL) {
printf("%d\n", current->value);
sleep(1);
current = current->next_node;
}
}
int main()
{
struct node root;
root.value = 3;
struct node *one;
one = add_node(&root, 5);
print_all(&root);
}
Your program exhibits undefined behavior: you are setting a pointer to a locally allocated struct here:
struct node child;
child.value = value;
child.next_node = NULL;
parent->next_node = &child;
return parent->next_node;
Since child is on the stack, returning a parent pointing to it leads to undefined behavior.
You need to allocate child dynamically to make it work:
struct node *pchild = malloc(sizeof(struct node));
// In production code you check malloc result here...
pchild->value = value;
pchild->next_node = NULL;
parent->next_node = pchild;
return parent->next_node;
Now that you have dynamically allocated memory, do not forget to call free on each of the dynamically allocated nodes of your linked list to prevent memory leaks.
add_node returns a pointer to a local variable which immediately goes out of scope and may be reused by other functions. Attempting to access this in print_all results in undefined behaviour. In your case, it appears the address is reused by the current pointer, leaving root->next_node pointing to root.
To fix this, you should allocate memory for the new node in add_node
struct node * add_node(struct node *parent, int value)
{
struct node* child = malloc(sizeof(*child));
if (child == NULL) {
return NULL;
}
child->value = value;
child->next_node = NULL;
parent->next_node = child;
return child;
}
Since this allocates memory dynamically, you'll need to call free later. Remember not to try to free root unless you change it to be allocated using malloc too.
I have this code :
typedef struct node
{
int data;
struct node *left;
struct node *right;
} node;
void Build (node *root , int i)
{
if (i < 7)
{
root = (node *)malloc (sizeof(node));
root->data = i;
Build(root->left,2*i+1);
Build(root->right,2*i+2);
}
else
root = NULL;
}
void Print (node *root)
{
if (root)
{
printf ("%d ",root->data);
Print(root->left);
Print(root->right);
}
}
void main()
{
node *tree;
Build(tree,0);
Print(tree);
}
two things that I dont understand ,
1. why can't I pass Build(tree,0) ? it says it's uninitialized , but why shuold I care if it's uninitialized ? I'm allocating all the memory needed straight away so it's gonna be pointing on the new allocated node.
how can I fix this code? thank you!!!
Your node * to tree is uninitialized.
node *tree;
That matters because the code line
root = (node *)malloc (sizeof(node));
allocates memory to a local copy of root. Once you leave function scope of Build, the copy of root goes out of scope. Memory leak.
Remember, everything is passed by value in C.
If you really want Build to allocate the memory, the signature would have to be
void Build (node **root , int i)
and your code in that method would have to refer to *root instead of root.
Parameters are passed by value - the location in memory is not actually passed. So when you call Build, you're just passing in the value of tree, which happens to be uninitialized. The Build function creates a local root variable with that value - when you set root = ... in Build, you're over-writing that undefined value with the new value, but that new value is still just in the local root variable - it is never seen by the tree variable in main.
What you really want to do is have Build return the newly created tree pointer:
node * Build(int i)
{
node *root;
...
root->left = Build(2*i+1)
...
return root;
}
void main()
{
...
tree = Build(0);
...
}