I have the Segmentation fault (core dumped) error.
main.c
#include "header1.h"
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char** argv) {
struct t_list *list = NULL;
doFill(list);
printf("%s\n", list->name);
free(list);
return 0;
}
header1.h
#ifndef HEADER1_H
#define HEADER1_H
struct t_list {
char *name;
struct t_list *next;
};
void doFill(struct t_list *list);
#endif
worker.c
#include "header1.h"
#include <stdlib.h>
void doFill(struct t_list *list) {
list = (struct t_list *) malloc(sizeof(struct t_list));
char *tmp = "somename";
list->name = tmp;
list->next = NULL;
}
When I run this (gcc -g main.c worker.c -o test) I get (on the line with printf in main.c):
Segmentation fault (core dumped)
In gdb I see:
Temporary breakpoint 1, main (argc=1, argv=0x7fffffffddf8) at main.c:8
8 struct t_list *list = NULL;
(gdb) next
9 doFill(list);
(gdb) step
doFill (list=0x0) at worker.c:6
6 list = (struct t_list *) malloc(sizeof(struct t_list));
(gdb) p list
$1 = (struct t_list *) 0x0
(gdb) next
7 char *tmp = "somename";
(gdb) p list
$2 = (struct t_list *) 0x0
As you can see malloc in worker.c doesn't allocate memory for the list variable (the pointer before and after malloc points at 0x0).
If I move the code from the doFill procedure in main.c it works correctly:
main.c
#include "header1.h"
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char** argv) {
struct t_list *list;
list = (struct t_list *) malloc(sizeof(struct t_list));
char *tmp = "somename";
list->name = tmp;
list->next = NULL;
printf("%s\n", list->name);
free(list);
return 0;
}
$ gcc -g main.c -o test
$ ./test
somename
How is it possible? What do I do wrong?
gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1)
You aren't receiving back the new value of list. In fact, passing list in is totally useless. Better to pass in the name for this node.
typedef struct t_list List;
List *newListNode(char *name) {
List *list = malloc(sizeof(*list));
if (!list) return NULL;
list->name = strdup(name);
if (!list->name) { free(list); return NULL; }
list->next = NULL;
return list;
}
char *strdup(char *src) { // if strdup doesn't already exist.
char *dst = malloc(strlen(src) + 1);
if (!dst) return NULL;
strcpy(dst, src);
return dst;
}
To add nodes to the front of the list:
List *listAdd(List *list, char *name) {
List *newnode = newListNode(name);
if (!newnode) return NULL;
if (list) newnode->next = list;
return newnode;
}
To delete the list, remember to delete the malloced strings:
void deleteList(List *list) {
for (List *next; list; list = next) {
next = list->next;
free(list->name);
free(list);
}
}
Parameters in C are passed by copy. The changes you make to list inside of doFill() are not propagated back to main(), which means that list is always NULL in main(). Try passing a pointer to pointer instead:
#include "header1.h"
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char** argv) {
struct t_list *list = NULL;
doFill(&list);
printf("%s\n", list->name);
free(list);
return 0;
}
And then change doFill() accordingly:
#include "header1.h"
#include <stdlib.h>
void doFill(struct t_list **list) {
*list = malloc(sizeof(**list));
char *tmp = "somename";
(*list)->name = tmp;
(*list)->next = NULL;
}
Related
I have this function and I want to test it and see if it does the job but it doesn't return
and when I try to change its return type to (t_list*) and make it return (node)
the compiler gives me segmentation fault
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct s_list
{
struct s_list *next;
void *data;
} t_list;
void ft_list_remove_if(t_list **begin_list, void *data_ref, int (*cmp)())
{
t_list *root;
t_list *node;
t_list *next;
root = *begin_list;
node = *begin_list;
while (root)
{
next = (*root).next;
if ((cmp)(root->data, data_ref) == 0)
{
if (root == *begin_list)
{
*begin_list = next;
}
node->next = next;
free(root);
}
node = root;
root = next;
}
}
in the main I created the "data_ref" and I made 5 structures some of them has "data_ref" and I linked them together
but when I call the function it gives me
segmentation fault
t_list *res;
res = ft_list_remove_if(ptr, str, strcmp);
ptr has the adress of the head of the list and str has the data_ref
I have a problem with solving a problem. I get continue the segmentation fault: 11 error, while I try this code. And every time I change the code the error pops up, and I don't know where the flaw is, so I would be greatfull if anyone sees the flaw.
I thank you in advance.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "dbg.h"
typedef struct node{
char *data;
struct node *next;
} node_t;
node_t **push(node_t **head, char *data){
node_t *new_node;
new_node = malloc(sizeof(node_t));
new_node->data = data;
new_node->next = *head;
*head = new_node;
free(new_node);
return head;
}
int main(int argc, char *argv[])
{
node_t **head;
char *data = "hoi";
char *data2 = "hallo";
head = malloc(20 * sizeof(node_t));
head = push(head, data);
head = push(head, data2);
printf("%s\n",(*head)[1].data);
free(head);
return 0;
}
Flaws:
Your push() function assigns the value of new_node to *head, making it accessible to the invoker of push(), but at the end of the function you free new_node, making it a dangling pointer. That's a good ground for segmentation faults.
head is a pointer to a pointer but is assigned the result of a malloc() invokation that seems to indicate that it should be a pointer to a node.
Your design is confusing: do you want to allocate the memory in push() or in main(). Certainly, both is not a good choice.
You are pointing to constant strings with non constant pointers. This is dangerous. Writing to the constant strings through these pointers could lead to segmentation faults too.
Here is a version of your program that works:
#include <stdio.h>
#include <stdlib.h>
struct node {
const char *data;
struct node *next;
};
static struct node *push(struct node *head, const char *data) {
struct node *node;
node = malloc(sizeof *node);
node->data = data;
node->next = head;
return node;
}
int main(int argc, char *argv[])
{
struct node *head = NULL;
const char *data = "hoi";
const char *data2 = "hallo";
head = push(head, data);
head = push(head, data2);
struct node *node = head;
while (node) {
printf("%s\n", node->data);
node = node->next;
}
return 0;
}
Note that I implemented a LIFO structure, aka. a stack, because a push() function usually applies to a stack.
A logical next step for you would be to implement the pop() function. Typically, I would recommend that pop() frees the node and returns the data. That would provide a nice symmetry for your API.
----------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char *val;
struct node *next;
};
void add_to_list(struct node **, char *);
void list_all_elements(struct node *);
int main (int argc, char **argv)
{
char *val;
struct node *head = NULL;
do {
scanf("%s",val);
add_to_list(&head, val);
}
while(val[0] != '\\');
list_all_elements(head);
}
void add_to_list(struct node **head, char *val)
{
//This produces a segfault
struct node *temp = malloc(sizeof *temp);
//EDIT - Fixed as per comments
temp->val = malloc(strlen(val) + 1);
strcpy(temp->val, val);
temp->next = NULL;
if(head!=NULL)
temp->next = *head;
*head = temp;
}
void list_all_elements(struct node *head)
{
while(head!=NULL) {
printf("%s\n",head->val);
head = head->next;
}
}
So this is what I compiled to implement a linked list. Now, for some reason malloc'ing the produces a segmentation fault.
To be sure, I replaced char * with a char [] and the code runs just fine. Is the malloc faulting due to this or is there some trivial error I can't seem to find?
You did not allocate the val in the main
char *val;
...
scanf("%s",val);
but here val is not allocated, when you do the scanf is going to sigsegv
You did not allocate memory that would be pointed to by variable val and where you are going to read a string.
char *val;
//...
do {
scanf("%s",val);
add_to_list(&head, val);
}
Variable val was not initialized so the program has undefined behaviour.
And function add_to_list is invalid. For example sizeof(val) has always the same value that is equal to the size of the pointer to char. It does not yield the size of a string pointed to by this pointer. Instead of the operator sizeof you shall use function strlen
The function could be written like
void add_to_list( struct node **head, const char *val )
{
struct node *temp = malloc( sizeof *temp );
size_t n = strlen( val );
temp->val = malloc( n + 1 );
strcpy( temp->val, val );
temp->next = *head;
*head = temp;
}
temp->val = malloc(sizeof(val));
Change sizeof(val) to strlen(val)+1.
So I was playing with stacks and made a generic Stack.h file and a Stack.c file which define the list and its functions, respectively, and when I try it out (stackdemo.c) it crashes when I pop from the list. I tried using void ** node members, being cautious with memory leaks, etc but nothing gets me past that. I am using the MinGW 32-bit gcc compiler and g++ for linking for Windows 7, giving no warnings.
I have a hunch that I might have to realloc the NODE struct every time push is called because the data member gets allocated after the NODE struct is, but I don't know how many bytes to allocate. I am assuming that the malloc of the NODE struct allocates two pointer variables and nothing more. I am not aware of any current memory leaks.
//Stack.h
#ifndef STACK_H
#define STACK_H`
#include "string.h"
typedef struct _Node
{
size_t size;
void *data;
struct _Node *next;
} NODE;
void push(NODE **head, void *data, size_t size);
void pop(NODE **head, void *data);
#endif
And stack.c
#include "Stack.h"
#include "stdlib.h"
#include "string.h"
void push(NODE **head, void *data,size_t size)
{
NODE *temp = (NODE *)malloc(sizeof(NODE*));
temp->size = size;
temp->data = malloc(size);
temp->next = *head;
memcpy(temp->data,data,size);
*head = temp;
}
void pop(NODE **head, void *data)
{
NODE *temp = *head;
if(temp)
{
data = malloc(temp->size);
memcpy(data,temp->data,temp->size);
*head = temp->next;
free(temp->data);
free(temp);
}
}
The test program:
#include "Stack.h"
#include "stdio.h"
int main(int argc, char **argv)
{
int n = 1;
NODE *head = NULL;
while(n)
{
printf("\nPlease enter a number to push or press -1 to pop, 0 to quit:\t");
scanf("%d",&n);
if(n > 0)
{
push(&head,&n,sizeof(int));
printf("Pushed %d on the stack",n);
}
else if(n == -1)
{
int i;
pop(&head,&i);
printf("Popped %d from the stack",i);
}
}
}
It crashes every time it gets to pop()
at pop : The following line is not necessary.
data = malloc(temp->size);
at push :
NODE *temp = (NODE *)malloc(sizeof(NODE*));
should be
NODE *temp = (NODE *)malloc(sizeof(NODE));
I'm trying to add items to a linked list. The code compiles OK but when I execute the program, it crashes before adding the first node. The code looks OK to me but I must be missing something.
The code uses a global linked list which is necessary for this problem. I think my usage of it may be what is causing the crash.
main.c
#include <stdio.h>
#include <stdlib.h>
#include "LinkedList.h"
int main (int argc, char* argv[])
{
LinkedList *canQueue;
int ii;
createList();
FILE* f;
f = fopen(argv[1], "r");
if(f==NULL)
{
printf("Error: could not open file");
return 0;
}
for(ii = 0; ii < 10; ii++)
{
TinCan* tempCan = malloc(sizeof(TinCan));
fscanf(f, " label_%d", &tempCan->label); /*Read info from file into label field*/
insertLast(canQueue, tempCan); /*Inserts the new can into linked list*/
}
return 0;
}
LinkedList.h
typedef struct TinCan
{
int label;
} TinCan;
typedef struct Node
{
TinCan* data;
struct Node *next;
} Node;
typedef struct LinkedList
{
Node *head;
} LinkedList;
void insertLast(LinkedList* list, TinCan *newData);
void createList();
extern LinkedList* canQueue;
LinkedList.c
#include <stdio.h>
#include <stdlib.h>
#include "LinkedList.h"
LinkedList *canQueue;
void createList() /*creates empty linked list*/
{
canQueue = malloc(sizeof(LinkedList));
canQueue->head = NULL;
}
void insertLast(LinkedList* list, TinCan *newData)
{
Node* newNode = malloc(sizeof(Node));
newNode->data = newData;
newNode->next = NULL;
if(list->head==NULL)
{
list->head=newNode;
}
else
{
Node* temp;
temp = list->head;
while(temp->next!=NULL)
{
temp = temp->next;
}
temp->next = newNode;
}
printf("Added to end");
}
Based on your response, you need to remove this declaration from main:
LinkedList *canQueue;
It is shadowing the global canQueue, which means later on when you call insertLast:
insertLast(canQueue, tempCan);
you are operating on an unintialized pointer.