Why am I getting a Segmentation Fault here? - c

#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <stdlib.h>
typedef struct pr_struct{
int owner;
int burst_time;
struct pr_struct *next_prcmd;
} prcmd_t;
static prcmd_t *pr_head = NULL;
static prcmd_t *pr_tail = NULL;
static int pending_request = 0;
static pthread_mutex_t prmutex = PTHREAD_MUTEX_INITIALIZER;
int add_queue(prcmd_t *node)
{
pthread_mutex_lock(&prmutex);
//code
prcmd_t *curNode = pr_head;
if(pr_head == NULL) { pr_head = node; return;}
while(curNode->next_prcmd)
{
curNode->next_prcmd = (prcmd_t*)malloc(sizeof(prcmd_t));
curNode = curNode->next_prcmd;
}
curNode->next_prcmd = node;
//
pending_request++;
pthread_mutex_unlock(&prmutex);
return(0);
}
int main()
{
if (pr_head == NULL)
{
printf("List is empty!\n");
}
prcmd_t *pr1;
pr1->owner = 1;
pr1->burst_time = 10;
add_queue(pr1);
prcmd_t *curNode = pr_head;
while(curNode->next_prcmd)
{
printf("%i\n", curNode->owner);
curNode = curNode->next_prcmd;
}
}
EDIT:
Here's what I have now...
int main()
{
prcmd_t *pr1;
pr1 = (prcmd_t*)malloc(sizeof(prcmd_t));
pr1->owner = 1;
pr1->burst_time = 10;
if (pr_head == NULL)
{
printf("List is empty!\n");
}
add_queue(pr1);
prcmd_t *curNode = pr_head;
printf("made it here 1\n");
while(curNode->next_prcmd)
{
printf("in the while loop\n");
printf("%i\n", curNode->owner);
curNode = curNode->next_prcmd;
}
}
output is:
List is empty!
made it here 1

pr1 is an uninitialized pointer to prcmd_t struct, dereferencing uninitialized pointer causes undefined behavior.
You need to allocate space for the structure on the heap / stack (depending on where it's gonna be used), so one option is:
// Allocate on stack
prcmd_t pr1;
pr1.owner = 1;
pr1.burst_time = 10;
add_queue(&pr1);
and second is:
//Allocae on heap
prcmd_t *pr1;
pr = (prcmd_t*)malloc(sizeof(prcmd_t));
pr1->owner = 1;
pr1->burst_time = 10;
add_queue(pr1);
Modifying your main method (and main only) to:
int main()
{
if (pr_head == NULL)
{
printf("List is empty!\n");
}
prcmd_t *pr1;
pr1 = (prcmd_t*)malloc(sizeof(prcmd_t));
pr1->owner = 1;
pr1->burst_time = 10;
add_queue(pr1);
prcmd_t *curNode = pr_head;
while(curNode && curNode->owner)
{
printf("%i\n", curNode->owner);
curNode = curNode->next_prcmd;
}
}
Outputs
List is empty!
1

It's hard to tell without you tellung us where...
But
you have to initialize
node->next_prcmd to null
why do you malloc in the while loop? you are
thereby destroing your current->next,
which in the next iteration is pretty
bad...
Mario

Related

Problem searching in my Binary Search Tree

Problem is function bin_search. it works steady on function insert. However, it gets frozen on function search. I think if it's fine on insert, it should be fine on search, but it isn't. Here is my code...
"bst.h":
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node {
int key;
void *data;
struct Node *left, *right;
void (*destroy)(void *data);
} node;
typedef struct Tree {
node *head;
char name;
} tree;
#define key(node) node->key
#define data(node) node->data
#define left(node) node->left
#define right(node) node->right
#define destroy(node) node->destroy
#define tree_head(tree) tree->head
"functions.c":
#include "bst.h"
int bin_search(node *curr, int key, int cnt, node **found) {
cnt++; printf("cnt+\n");
if (curr == NULL) {
return -1;
} else if (curr->key == key) {
printf("curr_key = key\n"); return cnt;
}
if (curr->key < key) {
printf("curr_key < key\n");
if (curr->right == NULL) {
*found = curr;
return -(cnt + 1);
}
return bin_search(curr->right, key, cnt, found);
} else {
printf("curr_key > key\n");
if (curr->left == NULL) {
*found = curr;
return -(cnt + 1);
}
return bin_search(curr->left, key, cnt, found);
}
}
int insert(tree *root, int key, void *data, void (*destroy)(void *data)) {
if (root->head == NULL) {
node* new_node = (node *)malloc(sizeof(node));
left(new_node) = NULL; right(new_node) = NULL; destroy(new_node) = destroy; key(new_node) = key; data(new_node) = data;
tree_head(root) = new_node;
printf("created first node\n"); return 1;
}
int cnt; node **found;
if ((cnt = bin_search(root->head, key, 0, found)) < 0) {
node* new_node = (node *)malloc(sizeof(node));
left(new_node) = NULL; right(new_node) = NULL; destroy(new_node) = destroy; key(new_node) = key; data(new_node) = data;
if ((*found)->key < key) {
(*found)->right = new_node;
} else {
(*found)->left = new_node;
}
printf("created a node at %d\n", -cnt); return 1;
} else {
printf("already exists in tree"); return -1;
}
}
int search(tree *root, int key, void **data) {
if (root->head == NULL) {
printf("tree is empty\n"); return -1;
}
int cnt; node **found;
if ((cnt = bin_search(root->head, key, 0, found)) < 0) {
return -1;
} else {
if ((*found)->key < key) {
*data = (*found)->right->data;
} else {
*data = (*found)->left->data;
}
return cnt;
}
}
"main.c":
#include "bst.h"
#define MAX_NUM 8
#define MAX_LEGNTH 200
int main() {
// create a tree
tree root; root.head = NULL; root.name = 'a';
FILE *inpt = fopen("list.txt", "r"); char buffer[MAX_LEGNTH];
int count = 0;
while (fgets(buffer, MAX_LEGNTH, inpt) != NULL) {
printf("adding: %d\n", atoi(buffer)); insert(&root, atoi(buffer), buffer, NULL);
count++;
}
fclose(inpt);
int result; void **found;
result = search(&root, 2, found); printf("%d\n", result); // problem in here!!
return 0;
}
what is the problem with my 'search' function. I can't find it.
Besides the utterly non-standard use of sizeof(void), you are not providing a correct out-parameter to search. The point of the found argument is to receive the node pointer if the prospect key was discovered. This...
int cnt;
node **found; // <== LOOK HERE
if ((cnt = bin_search(root->head, key, 0, found)) < 0) {
is not the way to do that. It should be done like this:
int cnt;
node *found = NULL;
if ((cnt = bin_search(root->head, key, 0, &found)) < 0) {
// ^^^^^^
and all references to found thereafter should be through found->, not (*found)->
This mistake is made in three different places in your code. The last one is semi-broken, but still broken nonetheless.
void **found = (void *)malloc(sizeof(void));
int result = search(&root, 2, found);
printf("%d\n", result);
That should use this:
void *found = NULL;
int result = search(&root, 2, &found);
printf("%d\n", result);
Whether the rest of your code is broken I cannot say, and frankly we're not in the business of being an online-debugger. Use your local debugger tools; that's what they're for. But the items listed above are definitely a problem.

cs50 pset5 unload problem - memory leakage

I am trying to solve the cs50 pset5. I am using a tries method.
I can insert word into the tries successfully. However, when i unload the memory, it fails. I am so stuck at the unload problem for a few days.
When I try the unload function, it stated that Erorr Message: double free or corruption (!prev): 0x000000000205d010 ***
It is probably due to my unload function, but i have drawn out the logic. It seems fine to me. Anyone has any idea where to amend?
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>
#define LENGTH 45
#define SIZE_OF_CHILD 27
typedef struct Node {
bool is_word;
struct Node* child[SIZE_OF_CHILD];
} Node;
Node* root;
Node* temp;
Node* create_node(Node* node);
void test();
int cal_key(char c);
Node* insert(const char* word);
void unload(Node* node);
int main() {
root = malloc(sizeof(Node));
if (root == NULL) {
exit(0);
}
root = create_node(root);
temp = malloc(sizeof(Node));
if (temp == NULL) {
exit(0);
}
test();
}
// **************** function to create a node *******************
Node* create_node(Node* node) {
node->is_word = false;
for (int i = 0; i < SIZE_OF_CHILD; i++) {
node->child[i] = NULL;
}
return node;
}
//************* calculate the key value ************
// Assume that the input is in lower case
int cal_key(char c) {
if (isalpha(c)) {
if (islower(c)) {
return c - 'a';
}
else {
return c + 32 -'a';
}
}
else {
return SIZE_OF_CHILD - 1;
}
}
//*************** function to insert an item in the the node ***********
Node* insert(const char* word) {
int str_len = strlen(word);
temp = root;
int key;
for (int i = 0; i < str_len; i++) {
key = cal_key(word[i]);
if (temp->child[key] == NULL) {
Node* node = malloc(sizeof(Node));
if (node == NULL) {
fprintf(stderr, "Error in creating node\n");
exit(0);
}
node = create_node(node);
temp->child[key] = node;
}
temp = temp->child[key];
}
temp->is_word = true;
return root;
}
//***************** function to unload a function ********************
void unload(Node* node) {
// This is to find the last node
for (int i = 0; i < SIZE_OF_CHILD; i++) {
if (node->child[i] != NULL) {
unload(node->child[i]);
}
free(node);
}
}
void test() {
root = insert("Peter");
unload(root);
}

Linked List pointers prob

I do not know why this is not working.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// struct of list
typedef struct noeud
{
int adresse, taille, temp;
struct noeud* suivant;
} * liste;
int random(int a, int b)
{
return (a + (rand() % ((b + 1) + a)));
}
void initialisation(liste* LBO)
{
*LBO = NULL;
}
I think it's here the problem when I create q (q is created to point to the previous node).
void creation(liste* LBO)
{
liste q, prec = NULL;
int i = 0;
srand(time(NULL));
while (i < 3)
{
printf("%d", i);
q = malloc(sizeof(liste));
if (*LBO == NULL)
{
q->adresse = 0;
q->taille = random(5, 45);
q->temp = random(5, 15);
q->suivant = *LBO;
*LBO = q;
i++;
}
else
{
prec = *LBO;
q->taille = random(5, 45);
q->temp = random(5, 15);
q->adresse = prec->adresse + prec->taille;
q->suivant = *LBO;
*LBO = q;
i++;
}
}
}
void affichage(liste LBO)
{
printf("\nvoici ta liste \n ");
while (LBO != NULL)
{
printf("%d-->", LBO->taille);
LBO = LBO->suivant;
}
if (LBO == NULL)
printf("NULL");
}
int main()
{
// or here
printf("Hello world!\n");
liste LBO;
initialisation(&LBO);
creation(&LBO);
affichage(LBO);
return 0;
}
There are several issues:
Instead of calling
initialisation(&LBO);
which is not really wrong, just write:
LBO = NULL;
Then don't hide pointers with typedefs, it only adds confusion.
Instead of:
typedef struct noeud
{
int adresse, taille, temp;
struct noeud* suivant;
} *liste;
Write:
struct noeud
{
int adresse, taille, temp;
struct noeud* suivant;
};
and use struct noeud* instead of liste.
Now the real problem:
This is wrong. Here you allocate the size for a pointer, but you need to allocate the size for the whole structure:
q = malloc(sizeof(liste));
which is actually the same as:
q = malloc(sizeof(struct noeud*))
but you need:
q = malloc(sizeof(struct noeud))
You see now why hiding pointers with typedefs is a bad idea.
So here is the corrected version of your program (#includes ommitted for brevity):
struct noeud
{
int adresse, taille, temp;
struct noeud* suivant;
};
int random(int a, int b)
{
return (a + (rand() % ((b + 1) + a)));
}
void creation(struct noeud** LBO)
{
struct noeud* q, *prec = NULL;
int i = 0;
// srand(time(NULL)); <<<<< don't call srand here, call it once at the
// beginning of the program
while (i < 3)
{
printf("%d", i);
q = malloc(sizeof(struct noeud));
if (*LBO == NULL)
{
q->adresse = 0;
q->taille = random(5, 45);
q->temp = random(5, 15);
q->suivant = *LBO;
*LBO = q;
i++;
}
else
{
prec = *LBO;
q->taille = random(5, 45);
q->temp = random(5, 15);
q->adresse = prec->adresse + prec->taille;
q->suivant = *LBO;
*LBO = q;
i++;
}
}
}
void affichage(struct noeud* LBO)
{
printf("\nvoici ta struct noeud* \n ");
while (LBO != NULL)
{
printf("%d-->", LBO->taille);
LBO = LBO->suivant;
}
// if (LBO == NULL) <<<<<<<<<<< drop this, LBO is always NULL here
// but it doesn't hurt, it's just useless
printf("NULL");
}
int main()
{
srand(time(NULL)); // <<<<<<<<<<<<< call srand here
struct noeud* LBO;
LBO = NULL;
creation(&LBO);
affichage(LBO);
return 0;
}
There is still room for improvement, especially the creation function is somewhat awkward.
Also look at the comments with <<<<<<<<<<<, there are minor corrections

Inserting and Removing from Linked List

This is a hashtable implementation.
I have the insert kinda working but how do I return the linked list?
I know that the remove is not done yet but I understand the concept, my problem is returning the adjusted list.
I tried to make the hashtable a global variable but the programming would force when I ran it.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
#include <string.h>
struct node {
char * data;
struct node * next;
};
struct hashtable {
struct node ** table;
int size;
int nentries;
};
struct hashtable * hashtable_new(int size) {
struct hashtable * result;
result = malloc(sizeof(struct hashtable));
result -> size = size;
result -> nentries = 0;
result -> table = malloc(sizeof(struct node) * size);
int i = 0;
for (i = 0; i < result->size; i++) {
result->table[i] = NULL;
// result->table[i]->data = NULL;
}
return result;
}
unsigned hash_string(struct hashtable *this, char * str) {
unsigned hash = 0;
int i = 0;
for ( i = 0; str[i] != '\0'; i++ ) {
hash = hash * 37 + str[i];
}
//return hash;
return hash % this-> size;
}
void hashtable_free(struct hashtable * this) {
int i;
struct node *table_nodes, *current, *next;
for(i = 0; i<this->size; i++) {
table_nodes = this->table[i];
current = table_nodes;
while (current != NULL){
next = current->next;
free(current);
current = next;
}
this->table[i] = NULL;
}
free(&this->table);
free(&this->size);
free(&this->nentries);
free(this);
}
void hashtable_insert(struct hashtable * table, char * string) {
struct node * new_node;
unsigned index = hash_string(table, string);
if(table->table[index] == NULL) {
printf("\nIndex: %d", index);
new_node = malloc(sizeof(struct node));
new_node -> next = table->table[index];
new_node -> data = string;
printf("\nData: %s", new_node->data);
table -> table[index] = new_node;
table -> nentries++;
printf("\n");
} else {
new_node = malloc(sizeof(struct node));
new_node->data = string;
new_node->next = NULL;
struct node * current = table->table[index];
struct node * next;
int size = 1;
while (current != NULL) {
next = current->next;
//if(current->data == string){
//return;
//}
if(current-> next == NULL){
//last element in list
current->next = new_node;
table->nentries++;
size++;
printf("\nIndex: %d", index);
printf("\nSize: %d", size);
printf("\nData: %s", current->next->data);
printf("\n");
return;
}
current = next;
size++;
}
}
}
void remove_hash(struct hashtable * this, char * item) {
//unsigned index = hash_string(this, item);
}
int lookup(struct hashtable * this, char * item) {
struct node *temp;
unsigned int index = hash_string(this, item);
temp = this->table[index];
while(temp != NULL) {
// do something
printf("%s, ", temp->data);
if(temp->data == item) {
printf("found %s\n", temp->data);
}
temp = temp->next;
}
return 0;
}
void print(struct hashtable * this) {
int i = 0;
printf("\n Size %d \n", this->size);
if(this == NULL) {
printf("Please construct the hashtable");
return;
}
for (i = 0; i < this->size; i++) {
if(this->table[i] == NULL) {
printf("\n %d: <empty>", i);
} else {
printf("\n %d: %s ", i, this->table[i]->data);
if(this->table[i]->next != NULL) {
printf("%s ", this->table[i]->next->data);
}
}
}
}
int main(int argc, char **argv) {
//struct node *theNode;
struct hashtable *theHash;
theHash = hashtable_new(9);
hashtable_insert(theHash, "I");
hashtable_insert(theHash, "am");
hashtable_insert(theHash, "a");;
hashtable_insert(theHash, "fish");
hashtable_insert(theHash, "glub");
print(theHash);
hashtable_insert(theHash, "glub");
lookup(theHash, "I");
print(theHash);
//printf("\n\n\n");
hashtable_free(theHash);
//print(theHash);
return 0;
}
Since C doesn't let you pass by reference, you can try returning the hashtable then reassigning your variable with the result of hashtable_insert:
struct hashtable *hashtable_insert(struct hashtable *table, char *string) {
// awesome code here
return current;
}
And then call it with:
theHash = hashtable_insert(theHash, "Wow!");

Error C2440: 'function' : cannot convert from 'node *' to 'node'

I get this error when i try to run the program:
Error C2440: 'function' : cannot convert from 'node *' to 'node'
And i can't figure out what i'm doing wrong when i'm calling the method destroy_node with first_node as argument.
int dequeue(int *data)
{
node *first_node;
int result = 0;
if(queueref.first != NULL){
first_node = queueref.first;
data = (int*) queueref.first->data;
queueref.first = first_node->next;
result = destroy_node(first_node);
}
return result;
}
static int destroy_node(node *node_ref)
{
int data = 0;
free(node_ref);
if(node_ref == NULL){
data = 1;
}
return data;
}
Thanks for the help!
Edit:
The whole class and its this code that givs an error: result = destroy_node(first_node);
#include <stdlib.h>
#include <stdio.h>
typedef struct node {
int data;
struct node *next;
} node;
typedef struct {
struct node *first;
struct node *last;
} queue_c;
static queue_c queueref;
//Funktionsprototyper
#include "queue.h"
static int destroy_node(node node_ref);
static node *create_node(int data);
int enqueue(int data)
{
node *new_node, *last_node;
int result = 0;
new_node = create_node(data);
if(new_node != NULL){
if(queueref.first != NULL){
queueref.first = new_node;
queueref.last = new_node;
}
else{
queueref.last->next = new_node;
queueref.last = new_node;
}
result = 1;
}
return result;
}
static node *create_node(int data)
{
node *noderef;
noderef = (node*) malloc(sizeof(node));
noderef->data = data;
noderef->next = NULL;
return noderef;
}
int dequeue(int *data)
{
node *first_node;
int result = 0;
if(queueref.first != NULL){
first_node = queueref.first;
data = (int*) queueref.first->data;
queueref.first = first_node->next;
result = destroy_node(first_node);
}
return result;
}
static int destroy_node(node *node_ref)
{
free(node_ref);
return node_ref == NULL;
}
void print_queue()
{
node *curr_ptr = queueref.first;
if(curr_ptr != NULL){
while(curr_ptr != NULL){
printf("%d -> ", curr_ptr->data);
curr_ptr = curr_ptr->next;
}
}
else{
printf("Kön är tom!");
}
}
int delete_node(int data)
{
int result = 0;
node *curr_ptr;
node *prev_ptr;
node *temp_ptr;
if(queueref.first == NULL){
printf("Kön är tom!");
}
else if(queueref.first->data == data){
temp_ptr = queueref.first;
queueref.first = queueref.first->next;
result = destroy_node(temp_ptr);
}
else{
prev_ptr = queueref.first;
curr_ptr = queueref.first->next;
while(curr_ptr != NULL){
if(curr_ptr->data == data){
result = 1;
break;
}
prev_ptr = curr_ptr;
curr_ptr = curr_ptr->next;
}
if(result){
temp_ptr = curr_ptr;
prev_ptr->next = temp_ptr->next;
result = destroy_node(temp_ptr);
}
else{
printf("Ingen node innehöll talet: %d", data);
}
}
return result;
}
Edit:
Unwind where right i had forgotten to put a prototype in queue.h and i missed that when i went through the program.
There might be a conflicting prototype; the code as shown shouldn't generate this error. But it also should generate at least a warning since you're calling an unknown function; it would make more sense to put all of destroy_node() before the place where it's called, or add a prototype.
Note that the destroy_node() function is needlessly complex. It could be rewritten as:
static int destroy_node(node *node_ref)
{
free(node_ref);
return node_ref == NULL;
}

Resources