Reputation: 3520
I am trying to delete the last node in a linked list, but I seem to have some difficulties. Here is the code.
void sterge_ultimul(element *lista) {
element *p,*q;
while (p->urmator->urmator!=NULL)
p=p->urmator;
q=p->urmator;
p->urmator=NULL;
free(q);
}
English:
void delete_last(element *list) {
component *p, *q;
while (p->next->next != NULL)
p = p->next;
q = p->next;
p->next = NULL;
free(q);
}
I already did the function to remove the head of the list, so I don't think I need to worry about that.
It doesn't run, and if you could help, I would appreciate.
Thanks, Radu
Upvotes: 0
Views: 174
Reputation: 98
You didn't initialize p pointer. Its value is indeterminate.
Reading an uninitialized object is undefined behavior. Undefined behavior means anything can happen. Anything includes that your program can very well crash.
for C90, see 3.16 in the definition of undefined behavior, for C11, see 6.3.2.1p2 and for C99, see the C Committee answer in DR#338.
C90
undefined behavior: Behavior upon use [...] or of indeterminately valued objects [...]
(C11, 6.3.2.1p2)
"If the lvalue designates an object of automatic storage duration that could have been declared with the register storage class (never had its address taken), and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined."
Below are the correct functions :
void sterge_ultimul(element *lista)
{
element *p = lista , *q;
while (p->urmator->urmator!=NULL)
p=p->urmator;
q=p->urmator;
p->urmator=NULL;
free(q);
}
English
void delete_last(element *list)
{
component *p = list, *q;
while (p->next->next != NULL)
p = p->next;
q = p->next;
p->next = NULL;
free(q);
}
A general advice : Always make sure you have a strong reason when you see uninitialized pointers ( or variables and objects in general) in your code. This little check will save a lot of trouble for you debugging your code in future.
Upvotes: 1
Reputation: 12057
I would implement it like this:
void sterge_ultimul(element** p)
{
while(*p && (*p)->urmator)
p = &(*p)->urmator;
free(*p);
*p = 0;
}
With this version you can also delete the last element, when there is only one element in the list. It should be called with the address of the pointer to the list:
sterge_ultimul(&lista);
If the list only contains one element, the last element is deleted, and lista
will be 0
after the call.
Upvotes: 2
Reputation: 5487
Your p is never initialised, so it points to a random address in memory, and then you access it causing undefined behaviour.
What you want is to initialise p with the first element of the list (lista
). Then, you need to think about your logic, specifically what happens if you try to delete the last node of a linked list when there's only one node.
Upvotes: 3
Reputation: 87451
Initialize p:
void sterge_ultimul(element *lista) {
element *p = lista, *q;
while (p->urmator->urmator!=NULL)
p=p->urmator;
q=p->urmator;
p->urmator=NULL;
free(q);
}
Also I would add some error handling to check if the list is too short:
int sterge_ultimul(element *lista) {
element *p = lista, *q;
if (!p || !p->urmator) return 0; /* error, list is too short */
while (p->urmator->urmator!=NULL)
p=p->urmator;
q=p->urmator;
p->urmator=NULL;
free(q);
return 1;
}
Upvotes: 2