Reputation: 167
so im doing this doubly linked list code, compiling works.. but executing gives me SIGSEGV. When i tried running valgrind it said that there is some uninitialised values.
My best guess would be that this is happening because malloc'd memory scope reach or smthing like.. idk maybe it gets dumped when the function ends?..im not sure, but it still says that there is some memory allocated and reachable...or maybe there is just some semantic error that im not aware of :/
Conditional jump or move depends on uninitialised value(s)
==14798== at 0x400848: push (in /home/mename/linkedlist/llist)
==14798== by 0x40088E: main (in /home/mename/linkedlist/llist)
==14798== Uninitialised value was created by a heap allocation
==14798== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14798== by 0x400879: main (in /home/mename/linkedlist/llist)
==14798== Use of uninitialised value of size 8
==14798== at 0x4E8476B: _itoa_word (_itoa.c:179)
==14798== by 0x4E8812C: vfprintf (vfprintf.c:1631)
==14798== by 0x4E8F898: printf (printf.c:33)
==14798== by 0x400793: printlist (in /home/mename/linkedlist/llist)
==14798== by 0x4008CD: main (in /home/mename/linkedlist/llist)
==14798== Uninitialised value was created by a heap allocation
==14798== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14798== by 0x400879: main (in /home/mename/linkedlist/llist)
==14798== Invalid write of size 8
==14798== at 0x40071B: pop (in /home/mename/linkedlist/llist)
==14798== by 0x4008D9: main (in /home/mename/linkedlist/llist)
==14798== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==14798== Process terminating with default action of signal 11 (SIGSEGV)
==14798== Access not within mapped region at address 0x0
==14798== at 0x40071B: pop (in /home/mename/linkedlist/llist)
==14798== by 0x4008D9: main (in /home/mename/linkedlist/llist)
==14798== The main thread stack size used in this run was 8388608.
0 -> 0 -> 0 -> 0 -> 0==14798==
==14798== HEAP SUMMARY:
==14798== in use at exit: 96 bytes in 4 blocks
==14798== total heap usage: 6 allocs, 2 frees, 1,144 bytes allocated
==14798==
==14798== LEAK SUMMARY:
==14798== definitely lost: 0 bytes in 0 blocks
==14798== indirectly lost: 0 bytes in 0 blocks
==14798== possibly lost: 0 bytes in 0 blocks
==14798== still reachable: 96 bytes in 4 blocks
==14798== suppressed: 0 bytes in 0 blocks
added other functions and their libs (pop; clearlist; *.h) changed/updated files as answers suggested
#ifndef CLEARLIST_H
#define CLEARLIST_H
#include "defs.h"
#include <stdlib.h>
int clearlist(node** head);
#endif
#ifndef POP_H
#define POP_H
#include "defs.h"
#include <stdlib.h>
int pop(node** head);
#endif
#ifndef PRINTLIST_H
#define PRINTLIST_H
#include "defs.h"
#include <stdlib.h>
#include <stdio.h>
int printlist(node* head);
#endif
#ifndef PUSH_H
#define PUSH_H
#include <stdlib.h>
#include "defs.h"
int push(node** head, int datainput);
#endif
#ifndef DEFS_H
#define DEFS_H
#define SUCCESS 0
#define FAIL -1
#define TRUE 0
#define FALSE -1
#define ALLOCFAIL -2
#define EMPTY -3
typedef struct Node{
struct Node* next;
struct Node* prev;
int data;
} node;
#endif
#include "defs.h"
#include "clearlist.h"
#include "pop.h"
#include "printlist.h"
#include "push.h"
int main(){
node *head;
head = (node*) malloc(sizeof(node));
push(&head, 10);
push(&head, 20);
push(&head, 30);
push(&head, 40);
printlist(head);
pop(&head);
printlist(head);
clearlist(&head);
return SUCCESS;
}
I will show just the functions involved until core dump which i think are responsible for the errors.
#include "push.h"
int push(node** head, int datainput){
/* Initialization of new node */
node* newptr = (node*) malloc(sizeof(node));
if(newptr == NULL){
return ALLOCFAIL;
}
newptr->next = NULL;
newptr->data = datainput;
/* Check for empty list */
if(head == NULL){
newptr->prev = NULL;
*head = newptr;
return SUCCESS;
}
/* Get to the end of list*/
node* headptr = *head;
while(headptr->next != NULL){
headptr = headptr->next;
}
headptr->next = newptr;
newptr->prev = headptr;
return SUCCESS;
}
#include "printlist.h"
int printlist(node* head){
/* Check if valid node or empty list */
if(head == NULL){
return EMPTY;
}
/* Move to first node if not already */
node* firstptr = head;
while(firstptr->prev != NULL){
firstptr = firstptr->prev;
}
/* Print entire list*/
while(firstptr != NULL){
if(firstptr->next != NULL){
printf("%d -> ", firstptr->data);
}
else{
printf("%d", firstptr-->data);
}
firstptr = firstptr->next;
}
return SUCCESS;
}
#include "defs.h"
#include "pop.h"
#include <stdio.h>
int pop(node** head){
/* If no node to pop */
if(*head == NULL){
return EMPTY;
}
/* Get to the end of list */
node* headptr = *head;
while(headptr->next != NULL){
headptr = headptr->next;
}
/*Pop last*/
node* temp = headptr->prev;
free(headptr);
/* po temp - Check if deleted the only node left*/
if(temp = NULL){
*head = NULL;
return EMPTY;
}
/* ...if not, make previous node the last node */
temp->next = NULL;
headptr = NULL;
return SUCCESS;
}
#include "clearlist.h"
int clearlist(node** head){
if(*head == NULL){
return SUCCESS;
}
/* Go to start */
while((*head)->prev != NULL){
*head = (*head)->prev;
}
/* Delete to the end */
while(*head != NULL){
node *prevnode = *head;
*head = (*head)->next;
free(prevnode);
}
return SUCCESS;
}
I dont really want to ask for a full solution, i want to learn something new but im a bit stuck on this one. :)
Upvotes: 0
Views: 1388
Reputation: 13580
The problem is this:
int main(){
node *head;
head = (node*) malloc(sizeof(node));
push(head, 10);
...
}
head
is only allocated, it is not initialized!
When you pass that not initialized pointer to push
,
if(head == NULL)
will be false and the block is not going to be executed, however the next block
node* headptr = head;
while(headptr->next != NULL){
headptr = headptr->next;
}
is executed. Remeber head
is not initialized, so headptr->next
points to
nowhere and you assign headptr = heatdptr->next
and so on.
Valgrind is telling you this: Uninitialised value was created by a heap allocation
The push
function should take a double pointer to head
and change where it's
pointing to when a new head is created:
int push(node **head, int datainput){
/* Initialization of new node */
node* newptr = (node*) malloc(sizeof(node));
if(newptr == NULL){
return ALLOCFAIL;
}
newptr->next = NULL;
newptr->data = datainput;
/* Check for empty list */
if(*head == NULL){
newptr->prev = NULL;
*head = newptr; // change where head is pointing to
return SUCCESS;
}
/* Get to the end of list*/
node* headptr = *head;
while(headptr->next != NULL){
headptr = headptr->next;
}
headptr->next = newptr;
newptr->prev = headptr;
return SUCCESS;
}
then you can call it like this:
int main(){
node *head = NULL; // <-- important initialization
push(&head, 10);
push(&head, 20);
...
}
Also note: don't cast malloc
edit
The printlist
has also a small errror, you are only printing the head, the
correct version should be
int printlist(node* head){
/* Check if valid node or empty list */
if(head == NULL){
return EMPTY;
}
/* Move to first node if not already */
node* firstptr = head;
while(firstptr->prev != NULL){
firstptr = firstptr->prev;
}
/* Print entire list*/
while(firstptr != NULL){
if(firstptr->next != NULL){
printf("%d -> ", firstptr->data);
}
else{
printf("%d", firstptr->data);
}
firstptr = firstptr->next;
}
puts("");
return SUCCESS;
}
Note that C does not have pass by reference, so if you want to modify a value of a variable in other function, you pass a pointer to that variable:
void foo(int *p)
{
*p = 8;
}
void bar(void)
{
int c = 4;
foo(&c);
// c is now 8
}
That same applies to pointers, if you want to change where a pointer is pointing to in another function, you have to pass a pointer to the pointer (aka double pointer):
void foo(char **str)
{
*str = "World";
}
void bar(void)
{
char *x = "Hello";
puts(x); // prints Hello
foo(&x);
// x points now to a different string literal
puts(x); // print World
}
That's what I'm doing in push
.
To prove that this is correct, see this: https://ideone.com/As5XDy
I've used my push
function (and the fix of printlist
) and the output is
10 -> 20 -> 30 -> 40
Also don't forget to write a function that frees the memory.
Upvotes: 2
Reputation: 36822
The problem is that malloc
ing doesn't initialize anything, for example:
node *head;
head = (node*) malloc(sizeof(node));
The values of the node could be anything, you need to set the pointers to NULL
head->prev = head->next = NULL;
Further, you should declare and initialize the node on a single line and don't cast the result of malloc, I'd also recommend the other sizeof
mechanism. There is a more robust way to zero-initialize everything in the node
if you are in C99 or later which is to use a composite literal
node* head = malloc(sizeof *head);
*head = (node){0};
Looking through the rest of your code I'm not positive if this is the same problem everywhere, but you should be following the above pattern for your own safety.
Upvotes: 3