This is a linked list queue implementation.
This is my program
int size(QueuePtr q)
{
QueuePtr temp = q->next;
int size = 0;
while(temp)
{
size++;
temp = temp->next;
}
return size;
}
where QueuePtr is defined like this
struct QueueElement
{
struct QueueElement *next;
int prio;
DataPtr data;
};
typedef struct QueueElement *QueuePtr;
My program crashes when an adress is pointing to nullspace but isnt null!
Bad arg exception
temp = 0xf00000000000000 (while is not aborted since temp != 0)
temp = temp->next (this line generates the exception)
My debugger said that I'm free(----) memory that has not been malloced. But that didnt help me much -
What does this adress mean? Can I simply change my while(something) statement?
If you don't initialize the next pointers to 0 then they can contain anything including non-valid pointers.
In a Debug build uninitialized memory usually has a recognizable pattern like 0xfeeefeee or 0xdeadbeef just so it can be recognized as uninitialized.
To fix this you should set the next pointer to 0 explicitly when you create a node:
QueuePtr createNode(int prio, DataPtr data){
QueuePtr node = (QueuePtr)malloc(sizeof(struct QueueElement));
node->next = null;
node->prio = prio;
node-> data = data;
return node;
}
Related
#include <stdio.h>
#include <malloc.h>
typedef struct Node {
int value; //4
struct Node* next; //4
}Node;
Node *create();
void add();
void del();
void search();
Node *create(int v) {
Node *first;
first = (Node *)(calloc(1,sizeof(*first)));
first->value = v;
first->next = NULL;
return first;
}
void add(Node **head,int v) {
Node *p;
p = (Node *)(calloc(1,sizeof(*p)));
p->value = v;
p->next = *head;
*head = p;
}
void search(Node *head) {
Node *p;
p=head;
while(p != NULL) {
printf("address is %d;value address is %d;next address is %d;next content is %d\n",p,&(p->value),&(p->next),p->next);
p = p->next;
}
}
int main() {
Node *head;
head = create(0);
add(&head,1);
add(&head,2);
add(&head,3);
search(head);
}
sizeof(Node) == 8, but why is every node's size in the heap is 16 bytes? thinks
(my system is 32bit).
struct node is 4bytes + 4bytes = 8bytes.
The nodes sizes aren't 16 bytes, it's just that malloc() chooses to skip 8 bytes of memory for some reason, likely for its own bookkeeping. If you want to conserve memory, do few large allocations, not many small ones, or else the bookkeeping overhead can cost quite a lot.
well, even if the memory allocated between calls to calloc() was continuous for you program (which you cannot make sure), don't forget that the lib c has 'private' data stored in the hunk of memory you allocated.
usually there is a header like:
struct hdr
{
size_t size; /* Exact size requested by user. */
unsigned long int magic; /* Magic number to check header integrity. */
struct hdr *prev;
struct hdr *next;
__ptr_t block; /* Real block allocated, for memalign. */
unsigned long int magic2; /* Extra, keeps us doubleword aligned. */
};
(code from)
You may see that the block actually the buffer of data that you'll get when calling malloc()/calloc(), is surrounded by a lot of extra data (ok, here is special case for debug, thus there are probably extra magics).
The errors involved in your code were logic errors related to the various list functions. When you have a create function, that functions job is to allocate memory for the node and assign any values required. It does not worry about which node it is dealing with.
Conversely, your add function does NOT allocate anything, it simply calls create to handle that work and then its job is merely properly wiring pointers and next->pointers to the proper node.
Since you are dealing with a head node that contains data, you have 3 possible conditions for add; (1) when head is NULL; (2) when head->next is NULL; and (3) all remaining additions.
Putting those pieces together and adding a print function, your code could look like the following:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int value; //4
struct Node* next; //4
} Node;
/* function prototypes */
Node *create (int v);
void add (Node **head, int v);
void del ();
void search (Node *head);
void printvalues (Node *head);
int main (void) {
Node *head = NULL;
// head = create(0);
add (&head,0);
add (&head,1);
add (&head,2);
add (&head,3);
printf ("\nsearching:\n\n");
search (head);
printf ("\nprinting:\n\n");
printvalues (head);
return 0;
}
/* create - only creates nodes */
Node *create (int v)
{
Node *new;
new = calloc (1, sizeof *new);
new->value = v;
new->next = NULL;
return new;
}
/* add does NOT create - only handles wiring */
void add (Node **head, int v)
{
Node *new = create (v);
if (!*head) {
*head = new;
return;
}
Node *p = *head;
while (p && p->next)
p = p->next;
if (!(*head)->next)
(*head)->next = new;
else
p->next = new;
}
void search(Node *head)
{
Node *p = head;
while (p != NULL) {
printf (" address is %p; next address is %p;\n", p, p->next);
p = p->next;
}
}
void printvalues (Node *head)
{
Node *p = head;
unsigned cnt = 0;
while (p != NULL) {
printf (" node[%2u] value: %d\n", cnt++, p->value);
p = p->next;
}
}
Output
$ ./bin/dbgllmess
searching:
address is 0x1acf010; next address is 0x1acf030;
address is 0x1acf030; next address is 0x1acf050;
address is 0x1acf050; next address is 0x1acf070;
address is 0x1acf070; next address is (nil);
printing:
node[ 0] value: 0
node[ 1] value: 1
node[ 2] value: 2
node[ 3] value: 3
Note: you are responsible for freeing the memory allocated when it is no longer needed. Let me know if you have any questions.
Regarding the real question "why is every node's size in the heap is 16 bytes?"
Well, you can't expect that one memory block will lay exactly at the end of where the previous memory block sits. you can't assume anything about how the heap is managed intenally. two blocks can sit in a gigabyte distance from one another even if they allcoated consequently with malloc.
On Windows , In order for the heap to keep track of the memory blocks allocated, each block gets few more bytes to hold meta-data of the memory block. this is called "Heap Entry", and it is probably why your blocks are a bit bigger.
but again, you can't assume anything of the blocks - positioning in the heap anyway.
C newbie here, and I can't seem to figure this one out. So I'm starting to implement a linked-list (just something basic so I can wrap my head around it) and I've hit a snag. The program runs fine, but I can't free() the data stored in my struct.
Here's the source:
#include <stdio.h>
#include <stdlib.h>
struct node {
struct node* next;
void* data;
size_t data_size;
};
typedef struct node node;
node* create_node(void* data, size_t size)
{
node* new_node = (node*)malloc(sizeof(node));
new_node->data = (void*)malloc(size);
new_node->data = data;
new_node->next = NULL;
return new_node;
}
void destroy_node(node** node)
{
if(node != NULL)
{
free((*node)->next);
//this line here causes the error
free((*node)->data);
free(*node);
*node = NULL;
printf("%s\n", "Node destroyed!");
}
}
int main(int argc, char const *argv[])
{
float f = 4.325;
node *n;
n = create_node(&f, sizeof(f));
printf("%f\n", *((float*)n->data));
if (n->next == NULL)
printf("%s\n", "No next!");
destroy_node(&n);
return 0;
}
I get this message in the program output:
malloc: *** error for object 0x7fff5b4b1cac: pointer being freed was not allocated
I'm not entirely keen on how this can be dealt with.
This is because when you do:
new_node->data = data;
you replaces the value put by malloc just the line before.
What you need is to copy the data, see the function memcpy
node* create_node(void* data, size_t size)
...
new_node->data = (void*)malloc(size);
new_node->data = data;
Here, (1) you are losing memory given by malloc because the second assignment replaces the address (2) storing a pointer of unknown origin.
Number two is important because you can't guarantee that the memory pointed to by data was actually malloced. This causes problems when freeing the data member in destroy_node. (In the given example, an address from the stack is being freed)
To fix it replace the second assignment with
memcpy (new_node->data, data, size);
You also have a potential double free in the destroy_node function because the next member is also being freed.
In a linked list, usually a node is freed after being unlinked from the list, thus the next node shouldn't be freed because it's still reachable from the predecessor of the node being unlinked.
While you got an answer for the immediate problem, there are numerous other issues with the code.
struct node {
struct node* next;
void* data;
What's up with putting * next to type name? You are using it inconsistently anyway as in main you got node *n.
size_t data_size;
};
typedef struct node node;
node* create_node(void* data, size_t size)
{
node* new_node = (node*)malloc(sizeof(node));
What are you casting malloc for? It is actively harmful. You should have used sizeof(*new_node). How about checking for NULL?
new_node->data = (void*)malloc(size);
This is even more unnecessary since malloc returns void * so no casts are necessary.
new_node->data = data;
The bug already mentioned.
new_node->next = NULL;
return new_node;
}
void destroy_node(node** node)
{
if(node != NULL)
{
How about:
if (node == NULL)
return;
And suddenly you get rid of indenation for the entire function.
free((*node)->next);
//this line here causes the error
free((*node)->data);
free(*node);
*node = NULL;
printf("%s\n", "Node destroyed!");
What's up with %s instead of mere printf("Node destroyed!\n")? This message is bad anyway since it does not even print an address of aforementioned node.
I am currently working on stacks right now. I am supposed to use the following structures and function prototypes:
typedef struct node_{
char data;
struct node_ *next;
}node;
typedef struct stack_{
unsigned int size;
node* stack;
}stack;
stack* create_stack();
void push(stack* s, char val);
Here is my actual code for create_stack() and push():
stack* create_stack()
{
stack *stack;
stack = malloc(sizeof(stack));
stack->size = 0;
stack->stack = NULL;
return stack;
}
void push(stack* s, char val)
{
stack *newStack;
newStack = create_stack();
newStack->stack->data = val;
newStack->stack = s->stack;
s = newStack;
}
I am getting a segmentation fault when I try to store char val into newStack->stack->data. How does this not work? What do I need to do to make this stack on top???
The push function is wrong.
void push(stack* s, char val)
{
stack *newStack;
newStack = create_stack(); /* new stack created, why not work on the existing one ? */
newStack->stack->data = val; /* you're writing to a NULL pointer */
newStack->stack = s->stack;
s = newStack; /* this will not be visible from outside the function */
}
First of all, you are trying to recreate a new stack for each call of this function, which is certainly not what is intended.
If you try to modify the value of s, it will not be visible from outside the function, and you will still have your original stack.
Then, you are accessing the stack->data member even though stack has no space allocated to it yet (because you set it to NULL). You actually set it right after, which is why it crashes, most probably.
You probably want to do something like this:
void push(stack* s, char val)
{
node * n;
/* go to the end of the "stack" */
n = s->stack;
while (n != NULL) {
n = n->next;
}
/* allocate memory for a new node */
n = malloc(sizeof(node));
/* initialize node */
n->data = val;
n->next = NULL;
/* increment stack size */
s->size++;
}
And as mentionned before, this is merely a singly-linked list which is not the best fit for a stack, because as it exists now, you have to follow the node pointers to reach the last element, which makes push and pop operations O(N).
A faster implementation would look like this:
void push(stack* s, char val)
{
node * first_node, * new_node;
first_node = s->stack;
/* allocate memory for a new node */
new_node = malloc(sizeof(node));
/* initialize node */
new_node->data = val;
new_node->next = first_node;
/* increment stack size */
s->stack = new_node;
s->size++;
}
The top of the stack is always the first node, and the performance is O(1).
Follow your code....
stack *newStack = create_stack(); // in push()
newStack = malloc(sizeof(stack)); // in create_stack()
newStack->stack = NULL; // in create_stack()
newStack->stack->data = val; // in push()... this is where you crash.
Because newStack->stack is a NULL pointer. Your create_stack() function sets it to NULL, and you then dereference it. You have to allocate a struct node somewhere.
This code also has some readability issues which might be contributing to the problem. You are naming variables the same names as their types, which is very confusing. Consider using some other naming pattern like stack_t for types and stack for variable names.
Consider the following code snippet
struct node {
char *name;
int m1;
struct node *next;
};
struct node* head = 0; //start with NULL list
void addRecord(const char *pName, int ms1)
{
struct node* newNode = (struct node*) malloc(sizeof(struct node)); // allocate node
int nameLength = tStrlen(pName);
newNode->name = (char *) malloc(nameLength);
tStrcpy(newNode->name, pName);
newNode->m1 = ms1;
newNode->next = head; // link the old list off the new node
head = newNode;
}
void clear(void)
{
struct node* current = head;
struct node* next;
while (current != 0)
{
next = current->next; // note the next pointer
/* if(current->name !=0)
{
free(current->name);
}
*/
if(current !=0 )
{
free(current); // delete the node
}
current = next; // advance to the next node
}
head = 0;
}
Question:
I am not able to free current->name, only when i comment the freeing of name, program works.
If I uncomment the free part of current->name, I get Heap corruption error in my visual studio window.
How can I free name ?
Reply:
#all,YES, there were typos in struct declaration. Should have been char* name, and struct node* next. Looks like the stackoverflow editor took away those two stars.
The issue was resolved by doing a malloc(nameLength + 1).
However,If I try running the old code (malloc(namelength)) on command prompt and not on visual studio, it runs fine.
Looks like, there are certain compilers doing strict checking.
One thing that I still do not understand is , that free does not need a NULL termination pointer, and chances to overwrite the allocated pointer is very minimal here.
user2531639 aka Neeraj
This is writing beyond the end of the allocated memory as there is no space for the null terminating character, causing undefined behaviour:
newNode->name = (char *) malloc(nameLength);
tStrcpy(newNode->name, pName);
To correct:
newNode->name = malloc(nameLength + 1);
if (newNode->name)
{
tStrcpy(newNode->name, pName);
}
Note calling free() with a NULL pointer is safe so checking for NULL prior to invoking it is superfluous:
free(current->name);
free(current);
Additionally, I assume there are typos in the posted struct definition (as types of name and next should be pointers):
struct node {
char* name;
int m1;
struct node* next;
};
I'm implementing a simple priority queue in C for a kernel and so I can't use any standard libraries. The queue holds a head node and each node points to the next in the queue.
typedef struct node node;
struct node {
node *next;
void *data;
};
typedef struct {
node *head;
int n;
} queue;
As you can see, each node holds it data in a void*. I'm having trouble converting this data to lets say an int when I pop the data off the stack.
//push data
int int_data = 100;
push(q, &int_data);
//...
//pop data
node* popped = pop(q);
int *pop_data = popped->data;
printf("pop data (100): %d\n", *pop_data);
Why can't I get the original value here? I seem to be printing a pointer value. Alternatively, is there a better way to handle this?
== edit (sorry should have included these):
void push(queue *q, void *data)
{
node new;
new.data = data;
node *new_ptr = &new;
if(is_empty(q))
{
q->head = new_ptr;
q->n++;
return;
}
int i;
node *curr = q->head;
for(i=0; i<q->n; i++)
{
curr = curr->next;
}
curr->next = new_ptr;
q->n++;
}
node* pop(queue *q)
{
node *curr = q->head;
q->head = curr->next;
return curr;
}
Is your code all in one function? If not, int int_data is getting popped off the stack (not your queue, the actual stack) which is probably why you are printing garbage; you are storing the address of a local variable.
I would suggest changing void* data to int data. (If you need to, you can store an address in an int and can cast it back to a pointer later.)
int int_data = 100;
push(q, int_data);
node* n = pop(q);
int num = n->data;
After reviewing your code again, you have the same problem when adding a new node. node new falls out of scope at the end of the function, so basically all of your nodes in your queue are pointing to invalid memory.
If the "pop" operation is in a different function:
The problem is likely because you're pushing a local variable into your queue.
When you go to pop, this address is no longer valid (or at least not pointing to an int value), so you're printing something strange. As the data is no longer pointing to your int, it probably looks like a memory address.
You can use the glib GPOINTER_TO_INT macro:
#define GPOINTER_TO_INT(p) ((gint) (glong) (p))
But please, take note with the doc note:
YOU MAY NOT STORE POINTERS IN
INTEGERS. THIS IS NOT PORTABLE IN ANY
WAY SHAPE OR FORM. These macros ONLY
allow storing integers in pointers,
and only preserve 32 bits of the
integer; values outside the range of a
32-bit integer will be mangled.
are you setting data = int_data (i.e. int --> void*) or data = &int_data (i.e. int* --> void *) ? In the former case, you have to write printf("pop data (100): %d\n", pop_data);