I am trying to code an easy list in C, which is able to store numbers.
With number SIZE, an index will be calculated and the numbers have to be stored in a kind of linear list at the array index.
However, sometimes I get a "segmentation fault", like 2 of 10 tries the output is correct.
I've gone a long search, but I couldn't find the problem.
Please keep in mind that my "solution" isn't implemented fully, so currently it's only working when the calculated index has no pointer thats stored. (Couldn't continue to code because of the error.)
Here is my code:
#define SIZE 3
#define NULL 0
typedef struct node_s node_t;
struct node_s {
node_t* next;
int number;
};
static node_t nodeArray[SIZE];
int addNumber(int numb){
int index = number % SIZE;
if(nodeArray[index].next == NULL){
node_t* node = (node_t*) malloc(sizeof(node_t));
node->number = number;
nodeArray[hash].next = node;
}
}
void print(){
for(int i = 0; i < SIZE; i++){
node_t* ptr = nodeArray[i].next;
while(ptr != NULL){
printf("%d -> ", ptr->number);
ptr = ptr->next;
}
printf("\n");
}
}
#include "dictionary.h"
#include <stdio.h>
int main(){
insert(1);
insert(2);
print();
return 0;
}
What causes the "segmentation fault" sometimes?
I appreciate any kind of help, thanks in advance!
Just after malloc you do init one member.
node->number = number;
But you do not init the other member, there is no
node->next = NULL;
Also, in your loop condition inside print(), you check ptr against NULL, but that is in most of the looping the non-initialised ptr->next from previous loop.
ptr = ptr->next;
I.e. you rely on it to be initialised to NULL.
That is probably causing the segfault.
Useful background, as pointed out by yano (thanks):
Malloc doesn't initialize memory to 0. In order to do that you can malloc followed by a memset or you can use calloc.
Related
I'm trying to build a binary search tree. Inserting an integer using insert function (only using 1 to 100 for testing) and appending the result to a file using inorder traversal. However, i'm getting a segmentation fault error. Using Visual Studio code on Macbook Pro 2020. Also tested on Codeblocks on Windows - filename.exe stops working and crashes.
#include <stdio.h>
#include <stdlib.h>
typedef struct node *BST;
struct node {
int data;
BST left;
BST right;
};
BST insert(BST root, int number) {
BST temp = NULL;
if (root == NULL) {
temp = *(BST *)malloc(sizeof(BST));
temp->left = NULL;
temp->right = NULL;
temp->data = number;
root = temp;
}
else if (root->data > number) {
insert(root->left, number);
}
else {
insert(root->right, number);
}
return root;
}
//returning null if number not found and pointer to root if found
BST find(BST root, int number) {
if (root == NULL) {
return NULL;
}
if (root->data > number) {
find(root->left, number);
}
else if (root->data < number) {
find(root->right, number);
}
else (root->data = number);
return root;
}
//printing number to file
void inOrder (BST root, FILE *fp) {
if (root == NULL) return;
inOrder(root->left, fp);
fprintf(fp, "%d", root->data);
inOrder(root->right, fp);
}
int main() {
BST root = NULL;
int n = 100;
int treeArray[n];
for (int r = 0; r < n; r++) {
treeArray[r] = r;
}
root = insert(root, treeArray[0]);
for (int x = 1; x < n; x++) {
insert(root, treeArray[x]);
}
FILE *treefile = fopen("print_tree.txt", "w");
inOrder(root, treefile);
fclose(treefile);
return 0;
}
Error: /bin/sh: line 1: 44278 Segmentation fault: 11 *file path redacted*
What am I doing wrong here? :(
Main problem is with this statement:
temp = *(BST *)malloc(sizeof(BST));
As it was already explained in the other answer clearly, I am going to skip that.
So you can do:
temp = malloc(sizeof (struct node));
OR
// to add : this helps in case the type of temp ever changes,
temp = malloc(sizeof(*temp));
Other minor logical changes:
In the find function, there is no need of this else if statement
// = or == doesn't matter now
else (root->data = number);
In the insert function, you forgot to link the nodes which you insert after your root node. So whenever you perform the inorder traversal, you only get the root node i.e 0 in your case.
Note:
typedef is used to make code more readable, but hiding the pointer using typedef creates confusion. So I would suggest not to typedef pointers.
You declare BST as:
typedef struct node *BST;
So, it is a pointer to a struct node and your problem is probably here:
temp = *(BST *)malloc(sizeof(BST));
You are allocating memory but the byte size you specified is that of BST, that is pointer to struct node, while you want to allocate a struct node.
You cast the returned value of malloc to a pointer to a BST, that is, a pointer to a pointer to a struct node. And then you de-reference it to assign the result to temp. So, what you assign to temp is a pointer to a struct node (correct) but the pointed object has the wrong size. Anyway, you should not cast the value returned by malloc (void *).
Things are much simpler than you apparently think: if you want to allocate a struct node (or anything else) pass its size to malloc. malloc returns a void * pointer to the allocated struct node that you can assign to any pointer variable without casting.
Note: you should check the returned value because if malloc fails it returns NULL and you should not use that.
Try this, instead:
temp = malloc(sizeof (struct node));
if(temp == NULL) {
fprintf(stderr, "%s:%d allocation failed\n", __FILE__, __LINE__);
exit(EXIT_FAILURE);
}
I assumed that an allocation error, in your case, is unrecoverable, adapt if it is.
Note: you could also, as suggested in comments, use:
temp = malloc(sizeof *temp);
which will always work, by construction. But as long as you are not completely comfortable with pointers and memory allocation I suggest that you use explicit types with malloc. It is a bit easier to read and understand, even if it is a bit less easy to maintain (if you change the type of temp).
But there are other problems with your code. Your insert and find functions are bogus. Understanding why is left as a debugging exercise.
Why cant I assign a pointer to a double pointer's pointer? I get segmentation fault every time.
#include <stdio.h>
int main() {
int **pointer1, *pointer2, *pointer3, var;
var = 10;
pointer3 = &var;
pointer1 = &pointer3;
pointer2 = *pointer1; //correcting my mistake, so this is now correct?
return 0;
}
The code I was actually working on, practicing linked list:
#include <stdio.h>
#include <stdlib.h>
typedef struct node_t {
int num;
struct node_t *next;
} node_t;
void insert(int, node_t**);
int main(void) {
int list;
node_t **head, *temp;
*head = NULL;
while (scanf("%d", &list) != EOF) {
insert(list, head);
}
temp = *head;
/*while (temp != NULL) { //here is the problem, if I remove this
//I get segmentation fault but it runs
printf("%d ", temp->num); //runs fine when I include it
temp = temp->next;
}*/
return 0;
}
void insert(int list, node_t **head) {
node_t *temp = malloc(sizeof(node_t));
temp->next = (*head);
temp->num = list;
(*head) = temp;
}
Just like what I put in the code comment, the above version of my code gets segmentation fault when I compile it without the while loop. But weirdly enough, it works fine once I include the while loop. After fiddling around, I suspect the culprit to be the double pointer in which I tried to assign the secondary address into a regular pointer.
But this version actually runs fine:
#include <stdio.h>
#include <stdlib.h>
typedef struct node_t {
int num;
struct node_t *next;
} node_t;
void insert(int, node_t**);
int main(void) {
int list;
node_t *head, *temp;
head = NULL;
while (scanf("%d", &list) != EOF) {
insert(list, &head);
}
temp = head;
while (temp != NULL) {
printf("%d ", temp->num);
temp = temp->next;
}
return 0;
}
void insert(int list, node_t **head) {
node_t *temp = malloc(sizeof(node_t));
temp->next = (*head);
temp->num = list;
(*head) = temp;
}
Over here I passed the address into the linked list function and essentially I'm doing the same thing but without the double pointer.
On a side note, I have seen many different implementations of linked lists. Mine requires the double pointer because I'm using a void insert(int, **node_t), but there are versions which returns the address and updates the head: node_t* insert(int, *node_t) and Global linked list: void insert(int). Just wondering which versions are actually recommended, easier to debug and beginner friendly.
Your first example segfaults because *pointer1 (and pointer1 before it) isn't pointing to anything. It's an uninitialized pointer that points to random garbage data in memory.
Trying to dereference such a pointer (**pointer1 = 10;) results in a segfault.
A solution to make your first example work would be to allocate some memory for the data you're trying to store :
int **pointer1, *pointer2;
int *data = malloc(sizeof(int));
pointer1 = &data;
**pointer1 = 10;
pointer2 = *pointer1;
free(*pointer1); //or free(data)
When you do this:
**pointer1 = 10;
What this says is "take the address stored in pointer1, dereference that address, take the address stored there, dereference again, and store the value 10 at that location".
It looks something like this:
pointer1
------- ------- ------
| .--|---->| .--|--->| 10 |
------- ------- ------
You're getting a segfault because pointer1 doesn't currently point anywhere.
This could work if you do something like this:
int **pointer1, *pointer2, value;
value = 10;
pointer2 = &value;
pointer1 = &pointer2;
In the case of the two "real" code snippets, the problem with the first piece of code is that you pass head uninitialized to insert, which then subsequently dereferences head. This is the same problem as above. The same thing happens again in main because head is still uninitialized after calling list because it was passed by value. The second piece of code works because you pass the address of head to insert, so subsequently dereferenced it is valid.
I was trying to implement circular queue functionality. I am a C++ coder and I found it surprising that in C, struct cannot have member functions. Anyway this is my implementation:-
#include <stdio.h>
#include <stdlib.h>
struct node
{
int nvalue;
struct node *next;
};
struct CLlist
{
struct node* head;
struct node* tail;
int size;
};
void insert(struct CLlist *l,int num)
{
struct node *n=malloc(sizeof(struct node));
n->nvalue=num;
n->next=NULL;
if((l->head==l->tail)==NULL)
{
l->head=l->tail=n;
}
else if(l->head==l->tail && l->head!=NULL)
{
l->head->next=n;
l->tail=n;
l->tail->next=l->head;
}
else
{
l->tail->next=n;
l->tail=n;
l->tail->next=l->head;
}
l->size++;
}
void print(struct CLlist *l)
{
int idno=1;
printf("printing the linked list with size as %d\n",l->size);
struct node *cptr;
for(cptr=(l->head);cptr!=(l->tail);cptr=cptr->next)
{
printf("The idno is %d and the number is %d\n",idno,cptr->nvalue);
idno++;
}
//this is to print the last node in circular list : the tail node
idno++;
cptr=cptr->next;
printf("The idno is %d and the number is %d\n",idno,cptr->nvalue);
}
int main()
{
struct CLlist a;
struct CLlist *l;
l=&a;
insert(l,2);
insert(l,5);
insert(l,7);
insert(l,10);
insert(l,12);
print(l);
return 0;
}
I get segmentation fault in the line
printf("The idno is %d and the number is %d\n",idno,cptr->nvalue);
why does the error occur? I guess I am not passing l by pointer by value (passing pointers as by value) properly. could somebody help me in pointing out where I am going wrong?
Thanks
You never initialize the variable a in the main function, so its contents is indeterminate and using the members of that structure will lead to undefined behavior.
Your code has two issues, the first one more serious.
Your first issue is that the head and tail members of your CLlist structure are not being initialized to NULL, which can (non-deterministically) keep any real data from being stored in your structure. This can be fixed by adding the following 2 lines in main just before the first insert call:
l->head = NULL;
l->tail = NULL;
Your second problem is in this line:
if((l->head==l->tail)==NULL)
While it looks like this is comparing both l->head and l->tail to NULL, it's actually comparing l->head to l->tail, and then comparing that boolean result to NULL, which is effectively 0. The line should be changed to:
if((l->head == NULL) && (l->tail == NULL))
This will individually test both the head and tail pointers, and will only take that branch if they are both NULL.
You have a pointer
struct node *cptr;
// You're probably trying to access an unassigned pointer head in the next step
for(cptr=(l->head);cptr!=(l->tail);cptr=cptr->next)
As per the standards, there is no requirement that
a->head & a->tail are initialized to NULL
when you did
struct CLlist a;
Standard ISO/IEC 9899:201x clause 6.7.9->10 states
If an object that has automatic storage duration is not initialized
explicitly, its value is indeterminate.
In fact you're:
struct CLlist a;
// missing something here.
struct CLlist *l;
l=&a;
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I'm loading a file into memory and I am doing so with the following statement:
if ((ch = fread(&temp[i],1,1,loadDict)) == EOF)
break;
But I receive a segmentation fault. Upon inspection using gdb I verified that the fault is happening at this line (the if statement, before the break). Why does it not see that it will fault (the whole point of using EOF)?
I thought it might be that I'm using the EOF in an if statement rather than within a while() statement. Is it possible to use EOF in an if statement?
Update: More Code
bool load(const char* dictionary)
{
FILE* loadDict = fopen(dictionary, "r");
char* new = malloc(sizeof(char)); // for storing the "new-line" character
*new = 0x0A;
// defines a node, which containes one word and points to the next word
typedef struct node
{
char* word;
struct node* next;
}
node;
node* head = malloc(sizeof(node));
node* temp = malloc(sizeof(node));
head->next=temp;
// copies a word from the dictionary file into a node
int* numStore = malloc(sizeof(int)); //count for number of words in dictionary
int num = 0;
int ch = 0; // to hold for EOF
int flag = 0; // for breaking out of while loop
while(true)
{
node* newNode = malloc(sizeof(node));
temp->next=newNode;
temp->word=malloc(46);
int i = -1;
do
{
i++;
if (!feof(loadDict) || !ferror(loadDict))
{
flag = 1;
break;
}
fread(&temp[i],1,1,loadDict);
if (memcmp (new, &temp[i], 1) == 0)
num += 1;
}
while(memcmp (new, &temp[i], 1) != 0);
temp=newNode;
if (flag == 1)
break;
}
numStore = #
return true;
}
typedef struct node
{
char* word;
struct node* next;
}
The structure that you defined can crash, at least the implementations I have seen has. The char* inside the node has no fixed value. So when you do :
node* head = malloc(sizeof(node));
The malloc() will allocate a memory of (taking 1 byte for char pointer, and an int size pointer for node, defaulting to 4 bytes on a 32-bit machine) 5 bytes. What happens when you read more than 5 bytes?
Also, you are needlessly complicating this:
int* numStore = malloc(sizeof(int));
If you want to store the number of words in the dictonary, straight away use an int numstore, less headache :)
while(true)
{
node* newNode = malloc(sizeof(node));
temp->next=newNode;
temp->word=malloc(46);
...
}
Now, this here is an interesting concept. If you want to read till the end of file, you have got two options:
1) use feof()
2) at the end of the loop, try this:
while(true)
{
....
if(fgetc(loadDict)==EOF) break; else fseek(loadDict,-1,SEEK_CUR);
}
Also, this line: temp->word=malloc(46);
Why are you manually allocating 46 bytes?
Armin is correct, &temp[i], while i does get allocated to 0, the do{...}while(); is completely unnecessary.
Also from man fread : http://www.manpagez.com/man/3/fread/
You are reading what looks to me like 1 character.
In my opinion, try something like this:
set a max value for a word length (like 50, way more for practical purposes)
read into it with fscanf
get its length with fscanf
allocate the memory
Also, you do not need to allocate memory to *head; It can be kept as an iterator symbol
I almost forgot, how are you going to use the returned list, if you are returning bool, and the *head is lost, thus creating a memory leak, since you can't deallocate the rest? And unless you are using c99, c doesn't support bool
/*Global declaration*/
typedef struct node
{
char* word;
struct node* next;
}node;
node *head, *tmp;
/* for the bool if you really want it*/
typedef enum { false, true } bool;
node* load(const char* dictionary)
{
FILE* loadDict = fopen(dictionary, "r");
char word[50];
int num = 0;
int len;
node *old;
while(true)
{
/*node* newNode = malloc(sizeof(node));
temp->next=newNode;
temp->word=malloc(46);*/
fscanf(loadDict,"%s ",word);
len = strlen(word);
tmp = malloc(len + sizeof(node));
strcpy(tmp->word,word);
tmp->next = NULL;
if(head==NULL)
{
head = tmp;
old = head;
}
else
old->next = tmp;
old = tmp;
num++;
if(fgetc(loadDict)==EOF) break; else fseek(loadDict,-1,SEEK_CUR);
}
printf("number of counted words::\t%d\n",num);
fclose(loadDict);
return head;
}
Also, please remember that i have only accounted for the act that words are separated by one space per, so please load the file t=like that, or change the algo :) Also, be sure to free the memory after using the program !
void freeDict()
{
node *i;
while(head!=NULL)
{
i = head;
head = head->next;
free(i);
}
}
Hope this helps :)
This compiles...I've now run it too. The error handling on failure to allocate is reprehensible; it should at minimum give an error message and should probably free all the allocated nodes and return 0 (NULL) from the function (and close the file).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node
{
char *word;
struct Node *next;
} Node;
Node *dict_load(const char *dictionary)
{
FILE *loadDict = fopen(dictionary, "r");
if (loadDict == 0)
return 0;
Node *head = 0;
char line[4096];
while (fgets(line, sizeof(line), loadDict) != 0)
{
size_t len = strlen(line); // Includes the newline
Node *node = malloc(sizeof(*node));
if (node == 0)
exit(1); // Reprehensible
node->word = malloc(len);
if (node->word == 0)
exit(1); // Reprehensible
memmove(node->word, line, len - 1); // Don't copy the newline
node->word[len-1] = '\0'; // Null terminate the string - tweaked!
node->next = head;
head = node;
}
fclose(loadDict);
return head;
}
If you've got to return a bool from the function, then you probably need:
static bool dict_load(const char *dictionary, Node **head)
If the argument list is fixed at just the file name, then you're forced to use a global variable, which is nasty on the part of the people setting the exercise. It's 'doable' but 'ugly as sin'.
The code above does work (note the tweaked line); adding functions dict_free() and dict_print() to release a dictionary and print a dictionary plus proper error handling in dict_load() and a simple main() allows me to test it on its own source code, and it works (printing the source backwards). It gets a clean bill of health from valgrind too.
You're use of temp[i] raises suspicion that you might be accessing outside memory.
To quote from K&R:
If pa points to a particular element of an array, then by definition pa+1 points
to the next element, pa+i points i elements after pa, and pa-i points i elements
before.
These remarks are true regardless of the type or size of the variables in
the array a. The meaning of ``adding 1 to a pointer,'' and by extension,
all pointer arithmetic, is that pa+1 points to the next object, and pa+i
points to the i-th object beyond pa.
I wrote a c program, compiled it and it ran fine. After a few compiles - it started giving me a segmentation fault. I renamed the folder, recompiled and it worked again.
Is this something normal? To have an inconsistent segmentation fault? I change the output name, change folder names etc.. and it bounces from giving segmentation fault to not giving seg fault. I don't know what to do anymore.
I mean, if it is a coding problem, seg fault should be consistent, right? I should get it every time. here's the code:
file my_set.c:
#include <stdio.h>
#include <stdlib.h>
#include "list.h"
/*
The program acceps a set of numbers from stdin until EOF
And then prints them (not storing duplicate numbers)
*/
int main ()
{
int num;
nodePtr head; /*head of the list*/
while (scanf("%d", &num) != EOF)
{
addToList(num, &head);
}
printList(head);
freeList(head);
return 0;
}
file list.c:
#include <stdio.h>
#include <stdlib.h>
#include "list.h"
/*
Implements a linked list, each element of which contains a dynamic array.
I used a linked list to maximize potential memory in case it is fragmented.
I use a dynamic array in each node to minimize the percentage of overhead
from creating a list (the pointer, the index...);
*/
/*
Adds number n to list *h
4 cases:
1. list is empty:
creating one
updating h with new list
creating a new dynamic array in the list
updating it and the index
2. can reallocate current node's array for 1 more int
3. cannot reallocate current node's array:
creating a new node
initializing it
4. cannot create a new node
printing the current list, an "out of memory error" and freeing all memory.
*/
void addToList(int n, nodePtr *h)
{
static nodePtr p; /*points to current last node*/
int *temp; /*for use in reallocation*/
if (!*h) /*first item of set*/
{
*h = malloc (sizeof(node));
(*h)->arr = malloc(sizeof(int));
(*h)->arr[0] = n;
(*h)->i = 1;
p = *h;
return;
}
/*if n is already in the list, no need to add it
the call comes after first item, because first item cannot be in the list*/
if(existsInList(n, *h)) return;
/*using realloc while still possible*/
if ((temp = realloc(p->arr, (p->i+1)*sizeof(int))))
{
p->arr = temp;
p->arr[p->i] = n;
p->i++;
return;
}
/*if realloc no longet possible - start new node*/
if ((p->next = malloc(sizeof(node))))
{
p = p->next;
p->arr = malloc(sizeof(int));
p->arr[0] = n;
p->i = 1;
return;
}
/*can no longer start new nodes - quit with error, after printing*/
printf("out of memory!");
printList(*h);
freeList(*h);
}
/*checks if n is in p assuming p is not null
it can asume so because the call for it comes after the check for first item*/
int existsInList(int n, nodePtr p)
{
int i;
for (; p ; p = p->next)
for (i = 0; i < p->i; i++)
if (p->arr[i] == n)
return 1;
return 0;
}
/*frees the list*/
void freeList(nodePtr p)
{
nodePtr temp = p;
if (!p) return; /*list is empty*/
while (p)
{
free(p->arr);
p = p->next;
free(temp);
}
}
/*prints the content of the list to stdout*/
void printList(nodePtr p)
{
if (!p) return;
int i;
printf("\n");
for (; p ; p = p->next)
for (i = 0; i < p->i; i++)
printf("%d ", p->arr[i]);
printf("\n");
}
file list.h:
/*
pointer to a node
declare a variable of this type to create a list
then start adding to the list
*/
typedef struct s *nodePtr;
/*the struct that represents each node of the list
reason for dynamic array is in "list.c"
*/
typedef struct s
{
int *arr;
int i; /*index for next num, also size of array;*/
nodePtr next;
}node;
/*Adds the int to list at nodePtr omitting duplicates*/
void addToList(int, nodePtr*);
/*prints a list*/
void printList(nodePtr);
/*returns 1 if an int exists in list referenced by nodePtr, 0 otherwise*/
int existsInList(int, nodePtr);
/*frees all dynamically allocated memory*/
void freeList(nodePtr);
Basically all I do is get numbers from stdin, put them in a list(no duplicates) and then print them. I use a list of dynamic arrays.
Initialize your variables!
int num = 0;
nodePtr head = NULL; /*head of the list*/
ADD: The inconsistent behaviour can come from debug vs release compilation, usually compilers in debug mode set the non-initialized variables to weird values like 0xDDDDDDDD to make the problem immediately visible. In release mode if the memory block is zeroed it will happen that the content of the variables is 0 but there is no guarantee for it.
You should check the returns values from malloc() in case it's returning NULL (out of memory).
Intermittent segfaults in c/c++ programs are usually caused by uninitialised memory, often in pointer variables.
You've posted a lot of code, which makes it hard to debug just be reading it. I suggest going through the code and, wherever a variable is declared, giving it an initial value (e.g. zero or NULL). Remember that the compiler will not initialise them for you.
You should probably start by initialising the values of num and head in main(). E.g.
int num = 0;
nodePtr head = NULL; /*head of the list*/
EDIT 1
Another bug is in addToList(). If the first if block in that function is not executed then the value of the local variable p will be uninitailised when you later call realloc(p->arr, ...). When you dereference p to get p->arr, ifp` is uninitialised then you will usually get a segfault.
EDIT 2
Two useful techniques when programming in C/C++ :
Always initialise variables at the point that you declare them. If you don't then their value is undefined. Note that this doesn't solve all problems. If you dereference an uninitialised pointer then you will usually get a segfault. If you initailise it to null and then dereference it then you will always get a segfault. Easier to debug, but it still crashes.
Always declare variables as near as possible to the point in the code that you first use them. This has the effect of reducing the chances of using an uninitialised variable because the compiler will generate an 'undeclared variable' error. The practice of declaring all variables at the start of a function is a hangover from old-style 'K&R' C, where you had to do that. Modern C doesn't require it.
So, instead of:
int foo() // Warning: bad code
{
int a;
int b;
func1();
a=func2(&b);
return a;
}
try something like:
int foo()
{
func1();
int b = 42;
int a = func2(&b);
return a;
}