Linked list in c adding to beginning of the list - c

Im trying to create a simple programme to add a value to a linked list.
the code does compile with out errors.
Im getting a segmentation fault when trying to execute the file.
I tried to debug using printf statements, but I don't get any output anywhere.
could someone point out what im doing wrong.
typedef struct in separate .h file, include files also in separate .h file
typedef struct s_list
{
struct s_list *next;
void *data;
} t_list;
void list_push_front(t_list **begin_list, void *data)
{
t_list *l;
l = (t_list*)malloc(sizeof(t_list));
if(l == NULL){
printf("No allocation");
}
printf("%s\n", l->data);
l->data = data;
l->next = *begin_list;
*begin_list = l;
printf("%s\n", l->data);
}
int main(void)
{
t_list *k;
k = (t_list*)malloc(sizeof(t_list));
if(k == NULL){
printf("No allocation");
}
printf("allocation");
char s[] = "Woow!";
k->data = "Hello";
k->next->data = NULL;
// k->next->next->data = NULL;
list_push_front(&k, s);
return(0);
}

In the printf call
l = (t_list*)malloc(sizeof(t_list));
if(l == NULL){
printf("No allocation");
}
printf("%s\n", l->data);
you are trying to output non-initialized memory pointed to by the pointer l->data. So the function invokes undefined behavior. Remove this call of printf. It does not make sense.
Also in main this statement
k->next->data = NULL;
is incorrect and also invokes undefined behavior. It seems you mean
k->next = NULL;

As a general point, always compile with the -Wall -Werror flags and run your code frequently (every couple of lines). This should help avoid a lot of the problems here. Use valgrind, asan or gdb to detect and diagnose memory issues like the ones in this program.
k->next->data = NULL; is illegal because k->next is uninitialized.
printf("%s\n", l->data);, same problem. You must initialize a value before use.
Functions should not produce side effects like printing. It's OK for temporary debugging, but beyond that it makes for noisy programs and essentially unusable functions. If you want errors, print to stderr and exit or use return values such as an enum or NULL to indicate errors.
Always free allocated memory.
No need to cast the result of malloc.
Use consistent indentation and formatting.
A possible rewrite:
#include <stdio.h>
#include <stdlib.h>
typedef struct ListNode {
struct ListNode *next;
void *data;
} ListNode;
ListNode *list_create(void *data) {
ListNode *node = malloc(sizeof(*node));
if (!node) {
fprintf(stderr, "%s %d: malloc failed\n", __FILE__, __LINE__);
exit(1);
}
node->data = data;
node->next = NULL;
return node;
}
void list_push_front(ListNode **head, void *data) {
ListNode *node = list_create(data);
node->next = *head;
*head = node;
}
void list_free(ListNode *head) {
while (head) {
ListNode *dead = head;
head = head->next;
free(dead);
}
}
int main(void) {
ListNode *list = list_create("a");
list_push_front(&list, "b");
list_push_front(&list, "c");
for (ListNode *curr = list; curr; curr = curr->next) {
printf("%s\n", (char *)curr->data);
}
list_free(list);
return 0;
}

Related

Why is my Professor's Linked List Printing Backwards?

I have a project that I'm working on for a Systems Programming course. I'm building off of my professor's code. (Please don't mind her lack of labelling, etc. - I'm gonna try to clean this up as best as I can.)
Does anybody know why her linked list code is printing backwards?
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Node {
char name[15];
char title[15];
int year;
struct Node *next;
struct Node *prev;
};
typedef struct Node *Box;
Box print_list(Box pointer);
Box insert_node(FILE *inputp);
int main() {
Box head = NULL, temp;
FILE *inputp, *outputp;
int i;
inputp = fopen("input.txt", "r");
outputp = fopen("output.txt", "w");
head = insert_node(inputp);
for (i = 0; i < 4; i++) {
temp = insert_node(inputp);
temp->next = head;
head = temp;
}
print_list(head);
return 0;
}
Box print_list(Box pointer) {
Box here = pointer;
while (here != NULL) {
printf("%s, %s, %d \n", here->name, here->title, here->year);
here = here->next;
}
return pointer;
}
Box insert_node(FILE *inputp) {
Box temp = NULL;
temp = (Box)malloc(sizeof(struct Node));
fscanf(inputp, "%s", &temp->name);
fscanf(inputp, "%s", &temp->title);
fscanf(inputp, " %d", &temp->year);
temp->next = NULL;
temp->prev = NULL;
return temp;
}
This program's purpose is to read a .txt file "playlist" of songs and create a linked list out of them. The input is:
Rachmaninov Concerto_No_2 1999
Mozart Symphony_No_41 2000
Vivaldi The_Seasons 2003
Beethoven Symphony_No_5 1994
Bach Toccatas 2005
While the program outputs:
Bach, Toccatas, 2005
Beethoven, Symphony_No_5, 1994
Vivaldi, The_Seasons, 2003
Mozart, Symphony_No_41, 2000
Rachmaninov, Concerto_No_2, 1999
(I also don't know why she included an output file in the code, all of the output is in the console, not stored in a file. Ignore that.)
The list prints in reverse order because you insert each new node at the beginning of the list. You should use a tail pointer to keep track of the end of the list.
Also note these remarks:
both the next and the prev links should be updated.
hiding pointers behind typedefs as in typedef struct Node *Box; is considered bad practice because it is confusing and error prone.
insert_node is a confusing name for a function that merely allocates a new node from file data.
insert_node should test if fscanf() succeeded at reading the data
fscanf(inputp, "%s", &temp->name); has undefined behavior if the name of the composer exceeds 14 bytes. The same applies to the title. The maximum number of characters to store into the destination arrays before the null terminator should be specified as %14s and these arrays should be defined with a larger length.
main should check if a node was successfully allocated and initialized from file data. Instead of hardcoding the number of nodes, one should iterate as long as nodes can be read from the file.
Here is a modified version:
#include <error.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Node {
char name[40];
char title[40];
int year;
struct Node *next;
struct Node *prev;
};
void print_list(const Node *pointer);
Node *read_node(FILE *inputp);
int main() {
Node *head = NULL;
Node *tail = NULL;
Node *node;
FILE *inputp, *outputp;
int i;
inputp = fopen("input.txt", "r");
if (!inputp) {
fprintf(stderr, "cannot open input.txt: %s\n", strerror(errno));
return 1;
}
outputp = fopen("output.txt", "w");
if (!outputp) {
fprintf(stderr, "cannot open output.txt: %s\n", strerror(errno));
return 1;
}
while ((node = read_node(inputp)) != NULL) {
if (!head) {
head = tail = node;
} else {
node->prev = tail;
tail = tail->next = node;
}
}
print_list(head);
// should free node list
return 0;
}
void print_list(const Node *pointer) {
while (pointer != NULL) {
printf("%s, %s, %d\n", pointer->name, pointer->title, pointer->year);
pointer = pointer->next;
}
}
Node *read_node(FILE *inputp) {
Node *temp = malloc(sizeof(*temp));
if (temp != NULL
&& fscanf(inputp, "%39s%39s%d", &temp->name, &temp->title, &temp->year) == 3) {
temp->next = NULL;
temp->prev = NULL;
return temp;
} else {
free(temp);
return NULL;
}
}

display contents of a single linked list, code crashes at exit

Here is my code in question
#include <stdio.h>
#include <stdlib.h>
typedef struct _node Node;
typedef void* Data;
struct _node
{
Data* data;
Node *next;
};
typedef struct _singleLinkedList SingleLL;
struct _singleLinkedList
{
Node *head;
Node *tail;
Node *current; //not used in this example
};
typedef struct _partls
{
int x;
int y;
}Parts;
Node *addhead(SingleLL *list, Data* data)
{
Node *newnode = (Node*)malloc(sizeof(Node));
if(newnode == NULL)
return NULL;
newnode->data = data;
if(list->head == NULL)
{
newnode->next = NULL;
list->tail = newnode;
}
else
{
newnode->next = list->head;
}
list->head = newnode;
return newnode;
}
typedef void(*DISPLAY)(void*);
void displayparts(Parts* part)
{
puts("part_x\t\tpart_y");
printf("%d\t\t%d\n",part->x, part->y);
putchar('\n');
}
void displaySingleLinkedList(SingleLL *list, DISPLAY display)
{
Node *current;
for(current = list->head; current != NULL; current = current->next)
display(current->data);
}
void initSLList(SingleLL *list)
{
list->head = NULL;
list->tail = NULL; //not used in this example
}
int main(void)
{
puts("\nlinked list test code");
SingleLL *sLinkedList;
//create an object
Parts *part1 = (Parts*) malloc(sizeof(Parts));
if(part1 == NULL)
{
puts("NULL");
exit(1);
}
part1->x = 32;
part1->y = 98;
//create one more object
Parts *part2 = (Parts*) malloc(sizeof(Parts));
if(part2 == NULL)
{
puts("NULL");
exit(1);
}
part2->x = 42;
part2->y = 18;
initSLList(&sLinkedList);
addhead(&sLinkedList, part2);
addhead(&sLinkedList, part1);
displaySingleLinkedList(&sLinkedList, (DISPLAY) displayparts);
return 0;
}
Question:
This is a test code, not a complete perfect looking snippet.It has flaws. I did try the debugger to pace it line by line... it breaks when executes the displayparts function, the debugger says: cannot access memory at address 0x0. Although it should be enough info, i think my mind has stalled and i can't figure it out.
Can you help spot the source of the problem/problems that crashes the code? What should i modify to make it work with no errors?
Your pointer handling seems off, in multiple places. Here,
void initSLList(SingleLL *list)
main():
SingleLL *sLinkedList;
initSLList(&sLinkedList);
initSLList is given the address of the pointer sLinkedList, i.e. a pointer to a pointer.
Also, you have
typedef void* Data;
Node *addhead(SingleLL *list, Data* data)
So since Data is a pointer, addhead expects a pointer to a pointer.
But you're giving it a pointer to a Parts structure.
Gcc warns about giving a pointer to an incompatible type in six different places. See what warning options your compiler has, and enable them.
I'd suggest very sparingly typedefing pointers to something that don't look like pointers, just to avoid confusions like this. It might be ok in some library interface though.
SingleLL *sLinkedList;
// ...
initSLList(&sLinkedList);
But initSLList() takes a SingleLL* while you're passing it a SingleLL**. I think you meant to declare sLinkedList as a concrete SingleLL rather than a pointer to one.
You should compile with warnings set to the most verbose level (-Wall in gcc will do the trick). This would have generated a warning for this and possibly other issues in the program. It's a great, although sadly not foolproof, way to protect yourself against the extreme ease of shooting yourself in the foot with C.

Learning C, segfailt confusion

I've been trying to teach myself c over spring break and it's been a lot more challenging than i had anticipated! I've made some good progress, however i seem to have hit a snag. I've been writing my own implementation of a doubly linked list. After about eight hours of plugging along, I've got what seems to be a fairly coherent program. The compiler is giving me the all clear ahead, and i've successfully built the project multiple times. Now, i started programming in java; so to my mind the aforementioned assurances constitute an ironclad guarantee of success. However C seems to c things differently (pardon the pun)! When i attempt to run my program, i get a 'segfault' run-time error. I've spent some time reading up on this error, and (as im sure i'm about to be informed) it's an issue of memory mis-allocation. I've tried to debug, but no matter where i set my breakpoints i cant seem to preempt the error. I'm in a bit of a quandry, and i'd really appreciate any insights y'all might have to offer me! I apologize for the monolith of text i've just scrawled out... and i'll try to keep the post script brief. Here's a rough outline of my setup:
NetBeans 6.8 IDE with Cygwin environment
Currently running windows 7 x64
I'll post my code below, but certainly don't feel obligated to go sifting through it. What i'm really hoping for is a few suggestions on how to handle segfaults in general. I get the feeling i'll be seeing them a lot, and i'd like to develop a strategy for troubleshooting this particular issue.
Thanks in advance! without you guys i'd be up a serious creek!
main.c
#include <stdlib.h>
#include <stdbool.h>
#include"dll.h"
int main(int argc, char** argv) {
VECT coord1;
coord1->x = 0.0012345;
coord1->y = 0.012345;
coord1->z = 0.12345;
LIST coords = init_list();
list_add(coords, coord1);
return (EXIT_SUCCESS);
}
dll.c (doubley linked list source file)
#include "dll.h"
#include <stdlib.h>
#include <string.h>
#include<stdbool.h>
#include"dll.h"
LIST init_list() {
LIST list = (LIST) malloc(sizeof (struct list));
list->length = 0;
list->first = NULL;
list->last = NULL;
list->destructor = free;
return list;
}
LIST_ITR list_iterator(LIST list, bool from_front) {
LIST_ITR iter = (LIST_ITR) malloc(sizeof (struct list_itr));
if (from_front) {
iter->current = list->first;
} else if (!from_front) {
iter->current = list->last;
} else return NULL;
iter->started = 0;
return iter;
}
void list_add(LIST list, VECT coords) {
NODE node = (NODE) malloc(sizeof (struct node));
node->coord_vector = coords;
if (list->first == NULL) {
node->prev = NULL;
node->next = NULL;
list->first = node;
list->last = node;
} else {
list->last->next = node;
node->prev = list->last;
node->next = NULL;
list->last = node;
}
list->length++;
}
VECT list_itr_current(LIST_ITR iter) {
if (iter->started && iter->current != NULL)
return iter->current->coord_vector;
else {
return NULL;
}
}
VECT list_itr_next(LIST_ITR iter) {
if (!iter->started && iter->current != NULL) {
iter->started = 1;
return iter->current->coord_vector;
}
if (iter->current != NULL) {
iter->current = iter->current->next;
return list_itr_current(iter);
}
return NULL;
}
VECT list_prev(LIST_ITR iter) {
if (!iter->started && iter->current != NULL) {
iter->started = 1;
return iter->current->coord_vector;
}
if (iter->current != NULL) {
iter->current = iter->current->prev;
return list_itr_current(iter);
}
return NULL;
}
VECT list_get_first(LIST list) {
return list->first->coord_vector;
}
VECT list_get_last(LIST list) {
return list->last->coord_vector;
}
VECT list_pop(LIST list) {
NODE last = list->last;
if (last == NULL) return NULL;
if (list->first == list->last) {
list->first = NULL;
list->last = NULL;
} else {
list->last = last->prev;
last->prev->next = NULL;
}
VECT data = last->coord_vector;
free(last);
list->length--;
return data;
}
VECT list_poll(LIST list) {
NODE first = list->first;
if (first == NULL)
return NULL;
if (list->first == list->last) {
list->first = NULL;
list->last = NULL;
} else {
list->first = first->next;
first->next->prev = NULL;
}
VECT data = first->coord_vector;
free(first);
list->length--;
return data;
}
void list_remove(LIST list, bool from_front) {
VECT data;
if (from_front)
data = list_poll(list);
else if (!from_front)
data = list_pop(list);
else return;
list->destructor(data);
}
void destroy_list(LIST list) {
NODE current = list->first;
NODE next;
while (current != NULL) {
next = current->next;
list->destructor(current->coord_vector);
free(current);
current = next;
}
free(list);
}
dll.h (doubley linked list header file)
#include<stdbool.h>
#ifndef _DLL_H
#define _DLL_H
#ifdef __cplusplus
extern "C" {
#endif
/* A C implementation of a doubly-linked list. Contains void pointer values.
Can be used as a LIFO stack of FIFO queue. */
#define FRONT 0
#define BACK 1
struct vector{
double x;
double y;
double z;
};
typedef struct vector* VECT;
struct node{
VECT coord_vector;
struct node* next;
struct node* prev;
};
typedef struct node* NODE;
struct list{
int length;
NODE first;
NODE last;
void (*destructor)(void*);
};
typedef struct list * LIST;
struct list_itr{
NODE current;
char started;
};
typedef struct list_itr * LIST_ITR;
//Initializes the list
LIST init_list();
//initializes the list iterator
LIST_ITR list_iterator(LIST list, bool from_front);
//append element to end
void list_add(LIST list, VECT coords);
//Gets the data stored in the first item of the list or NULL if the list is empty
VECT list_get_first(LIST list);
//Gets the data stored in the last item of the list or NULL if the list is empty
VECT list_get_last(LIST list);
//LIFO pop: remove element and return data
VECT list_pop(LIST list);
//FIFO poll: remove element and return data
VECT list_poll(LIST list);
//Deletes element and frees memory
void list_remove(LIST list, bool from_front);
//Delete list and free all memory
void destroy_list(LIST list);
//returns the data of the element pointed to by current
VECT list_itr_current(LIST_ITR list_itr);
//Increments the index of current by 1 and returns the data stored there
VECT list_itr_next(LIST_ITR list_itr);
//Decrements the index of current by 1 and returns the data stored there
VECT list_prev(LIST_ITR list_itr);
#ifdef __cplusplus
}
#endif
#endif /* _DLL_H */
You should build your code with -Wall flag to compiler. At compile time it will then print:
main.c:9:15: warning: ‘coord1’ is used uninitialized in this function [-Wuninitialized]
This points you to the problem.
coord1 is a pointer type, that you assign to, but coord1 has no memory backing it until it is initialized. In the following snippet coord1 is initialized by allocating memory to store it's components. This gets rid of the segfault.
VECT coord1 = NULL;
coord1 = (VECT)malloc(sizeof(struct vector));
if (NULL == coord1)
{
fprintf(stderr, "Out of memory!\n");
exit(1);
}
coord1->x = 0.0012345;
coord1->y = 0.012345;
coord1->z = 0.12345;
In general, segfaults happen when a program accesses memory that the operating system has not allocated to it. Unintialized pointers usually point to address zero, which is not allocated to any program. Always use gcc -Wall when compiling, this will many times point to these potential problems. Helped me find it right away.
Also, you could have declared your VECT type to be typedef struct vector (a non-pointer type).
VECT coord1;
VECT* v_coord1 = &coord1;
v_coord1->x = 0.0012345;
v_coord1->y = 0.012345;
v_coord1->z = 0.12345;`
Also, variable naming conventions can help here as well.
struct vector{
double x;
double y;
double z;
};
typedef struct vector VECT;
typedef struct vector* pVECT;

linked list operations (core dumped)

Recently I've been improving my programming skills by coding different data structures, and this is the very beginning!!!
Now I'm writing the linked list, but something annoyed happen and the trouble has been annoyed me for a long time since I am not quite sure about this error,
Segmentation fault(core dumped), but I did know I made something wrong in the operation of memory.
link_list.h:
struct LINK_LIST {
char *string;
struct LINK_LIST *next;
}link_list;
==============================
link_list.c:
#include<stdio.h>
#include<stdlib.h>
int init_link_list(struct LINK_LIST *new_link) {
//char *new_string;
int i;
//new_string = (char *)malloc(sizeof(char) * STRING_SIZE);
new_link = (struct LINK_LIST *)malloc(sizeof(struct LINK_LIST));
if (new_link==NULL) {
fprintf(stderr, "Insufficient memory!!!");
return ERROR;
}
//new_link->string = new_string;
new_link->string = NULL;
//new_link->next = NULL;
return OK;
}
Here I defined the init operation, then the insert operation:
int insert(struct LINK_LIST *link, int pos, char *in) {
int i;
if (get_length(link)>=STRING_SIZE) {
fprintf(stderr, "Link list is full!!!");
return ERROR;
}
else {
if (pos < 0 || pos-1 > get_length(link)) {
fprintf(stderr, "Invalid position");
return ERROR;
}
else {
i = 0;
do {
struct LINK_LIST *new_node;
init_link_list(new_node);
new_node->next = link->next;
link->next = new_node;
new_node->string = in;
i += 1;
} while(i<pos-1);
}
}
return OK;
}
You have a bug there :
struct LINK_LIST *new_node;
init_link_list(new_node);
In init_link_list, the value of the argument is modified :
new_link = (struct LINK_LIST *)malloc(sizeof(struct LINK_LIST));
but that modification is only local to the function ; once you get back to your calling function, that change is lost :
struct LINK_LIST *new_node;
init_link_list(new_node);
// Oops ! new_node's new value is lost !
You have a memory leak (the malloc's result is lost) and new_node is not initialized. When you try to access *new_node, you access a random position in memory, hence core dumps.
There are a few possible corrections, the easiest is to discard your OK/ERROR return values and return either a non-null pointer if malloc succeeded, or NULL if it failed :
struct LINK_LIST *init_link_list(void) {
struct LINK_LIST *new_link = malloc(sizeof(struct LINK_LIST));
if (new_link==NULL) {
fprintf(stderr, "Insufficient memory!!!");
return NULL;
}
new_link->next = NULL;
return new_link;
}
Then, code in insert becomes :
...
else {
i = 0;
do {
struct LINK_LIST *new_node = init_link_list();
// Note : here, should check whether new_node is NULL and deal with the situation
new_node->next = link->next;
link->next = new_node;
...

Retrieve data from a method of another class in C

I'm working on assignment for an operating systems class. We are given code to use to help us with our assignment, but I have little programming experience with C, and I can't figure out how to use it. What I'm trying to do is print the information at the head of the list. The list is a list of structs defined as
typedef struct
{
char name[NAME_MAX];
int lifetime;
} pcb_t;
int
List_head_info ( List_t *list, void **data )
{
int all_ok = 0;
*data = NULL;
if ((list != NULL) && (list->head != NULL)) {
*data = list->head->data;
all_ok = 1;
}
return all_ok;
}
I tried to display them with:
printf("test: %s", List_head_info(&processes, (void *)pcb)->name);
but I am given the error invalid type argument a->a when compiling.
When you call List_head_info(), you will get back two things:
A pointer (void *) to the head data, or NULL.
A status indicating whether the pointer is non-NULL.
If it returns successfully, you can convert (coerce, or cast) the void * to a pcb_t * and then use that to print the data.
How would I do that specifically?
Probably something a bit like this:
List_t list;
...code to initialize and maybe add things to the list...
void *head_data = 0;
if (List_head_info(&list, &head_data))
{
pcb_t *item = (pcb_t *)head_data;
printf("Lifetime: %.2d; Name: %s\n", item->lifetime, item->name);
}
Strictly, the initialization of head_data is superfluous; the code in List_head_info() always sets the value at least once (to NULL or 0) and sometimes twice (the second time to the data component of the head item on the list).
This is 'example code' with enough information in it to compile. I've 'reverse engineered' the list structures enough to make sense; the actual implementation will be different, of course. This compiles cleanly under fairly stringent GCC warning levels, with GCC 4.1.2 and 4.7.0 on Mac OS X 10.7.4. AFAICS, it avoids some complex issues related to 'strict aliasing' which you really don't want to have to worry about at this stage.
#include <stdio.h>
enum { NAME_MAX = 40 };
typedef struct Node Node;
struct Node
{
void *data;
Node *next;
};
typedef struct
{
Node *head;
Node *tail;
} List_t;
typedef struct
{
char name[NAME_MAX];
int lifetime;
} pcb_t;
extern int List_head_info(List_t *list, void **data);
extern void another_func(List_t processes);
void another_func(List_t list)
{
void *head_data = 0;
if (List_head_info(&list, &head_data))
{
pcb_t *item = (pcb_t *)head_data;
printf("Lifetime: %.2d; Name: %s\n", item->lifetime, item->name);
}
}
int
List_head_info ( List_t *list, void **data )
{
int all_ok = 0;
*data = NULL;
if ((list != NULL) && (list->head != NULL)) {
*data = list->head->data;
all_ok = 1;
}
return all_ok;
}

Resources