I am currently in a University program studying Data Structures in C and I am having a lot of trouble right now. I want to make clear that what I am asking help for is not for marks, just practice challenge problems.
The goal is to implement a stack using Linked Lists. By looking through the lecture notes I think I have most of the functions down. I need to demonstrate Push() and Pop() will an append and a pretend. Using Cygwin, I compiled with no errors. but when I try to run it, I get a "Segmentation Fault". What does this mean and how do I fix it? if I remove "stack = initLListStack();", the error disappears. Here is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct Link{
int *value;
struct Link *next;
}Link;
typedef struct LList1{
int *size;
Link *head;
}LList1;
typedef struct LListStack{
LList1 *llist;
}LListStack ;
LListStack *initLListStack(void)
{
LListStack *stack = (LListStack *) malloc(sizeof(LListStack)) ;
stack->llist->size = 0;
stack->llist->head = NULL;
return(stack);
}
void removefront(LList1 *llist)
{
if(llist->head != NULL){
llist->head = llist->head->next;
llist->size--;
}
}
Link *FindLastLink(LList1 *llist, Link *link)
{
if(link = NULL){
return(NULL);
}
else if(link->next == NULL){
return(link);
}
else{
return(FindLastLink(llist, link->next));
}
}
Link *FindSecondLastLink(LList1 *llist, Link *link)
{
if(link = NULL){
return(NULL);
}
else if(link->next->next == NULL){
return(link);
}
else{
return(FindSecondLastLink(llist, link->next));
}
}
void removelast(LList1 *llist)
{
Link *secondlastlink = (Link *) malloc(sizeof(Link));
secondlastlink = FindSecondLastLink(llist, llist->head);
secondlastlink->next = NULL;
llist->size--;
}
void prepend(int *newValue, LList1 *templist)
{
Link *node = (Link *) malloc(sizeof(Link));
node->value = newValue;
node->next = templist->head;
templist->head = node;
templist->size++;
}
void append(int *newValue, LList1 *templist)
{
Link *node = (Link *) malloc(sizeof(Link));
Link *lastlink = (Link *) malloc(sizeof(Link));
lastlink = FindLastLink(templist, templist->head);
node->value = newValue;
lastlink->next = node;
node->next = NULL;
templist->size++;
}
void prepush(int *value, LListStack *stack)
{
prepend(value, stack->llist);
}
void apppush(int *value, LListStack *stack)
{
append(value, stack->llist);
}
int prepop(LListStack *stack, int *value)
{
int result ;
if ((!isEmpty(stack)))
{
removefront(stack->llist);
result = 1 ;
}
else {
result = 0 ;
}
return(result) ;
}
int isEmpty(LListStack *stack)
{
int empty;
if (stack->llist->head == NULL)
return( 1 ) ;
else
return( 0 ) ;
}
int apppop(LListStack *stack, int *value)
{
int result ;
if ((!isEmpty(stack)))
{
removelast(stack->llist);
result = 1 ;
}
else
result = 0 ;
return(result) ;
}
//*******MAIN**********//
int main()
{
LListStack *stack = (LListStack *) malloc (sizeof(LListStack));
stack = initLListStack(); //if I take this away, I can run the program
return(0);
}
I don't have that much in Main() yet because I'm just trying to get it to run first. Initializing the Stack seems to be the problem.
Thanks for your help guys!
The problem is in your initLListStack() function:
LListStack *stack = (LListStack *) malloc(sizeof(LListStack)) ;
stack->llist->size = 0;
stack->llist->head = NULL;
return(stack);
The result of malloc is an uninitialized block of memory large enough to hold an LListStack struct.
The very first thing you do with that memory is read its llist member. Since this is uninitialized, you invoke undefined behavior which, fortunately, causes a segfault. (The compiler would be within the specification to send embarrassing e-mails to our instructor when this happens.)
You need to initialize llist before you can use that member in stack. Something like:
LListStack *stack = malloc(sizeof(*stack));
stack->llist = malloc(sizeof(*stack->llist));
stack->llist->size = 0;
stack->llist->head = NULL;
return stack;
Note that I've also removed some unnecessary casts and parentheses, and changed the sizeof operator to calculate the memory you need based on the pointer you're storing into.
A segmentation fault error is usually caused by trying to dereference an uninitialized pointer. In your case, you have allocated memory for stack in your initLListStack method but you haven't initialized it -- in particular the llist field is not initialized to any particular value. You need to allocate an LList1 and set the llist field to the newly-allocated memory.
LListStack *initLListStack(void)
{
LListStack *stack = (LListStack *) malloc(sizeof(LListStack)) ;
stack->llist->size = 0; // **this is probably where it crashes**
stack->llist->head = NULL;
return(stack);
}
You allocate stack ok, but you do not allocate stack->llist. So stack->llist is uninitialized and then you dereference it in stack->llist->size . Dereferencing an
uninitialized variable results in undefined behavior.
To fix this, allocate stack->list like this:
LListStack *initLListStack(void)
{
LListStack *stack = (LListStack *) malloc(sizeof(LListStack)) ;
stack->llist = (LListStack *) malloc(sizeof(LList1)) ; // ADD THIS LINE
stack->llist->size = 0;
stack->llist->head = NULL;
return(stack);
}
Related
I am implementing a stack using linked list in C, and I stumbled upon two issues:
I need the stack_pop function to return a valid value temp, that is the temporary node/cell, and therefore, I can't free it. So, 1) Do you think freeing each node for every pop function call is better than until the end using the stack_destroy() 2) How can I achieve both, free(temp) and return it at the same time in stack_pop?
How bad my implementation becomes not using exit(1) in both stack_push and stack_pop functions?
This is the implementation:
//// Stack
// Linked list
typedef struct {
int data;
Cell* next;
} Cell;
struct stack_l {
size_t count;
Cell *top;
};
typedef struct stack_l *Stack;
You've got stack_pop declared to return an int, but you're attempting to return a Cell * which doesn't make sense.
Copy the value in the popped cell to a local variable, free the popped cell, then return the value.
temp = stack->top;
stack->top = stack->top->next;
temp->next = NULL;
stack->count--;
int val = temp.data;
free(temp)
return val;
Also, it makes no sense to call exit in either stack_push or stack_pop as that ends the program.
I think it is a bit overcomplicated. You only need to remember the previous stack pointer. Nothing else
typedef struct stack
{
int data;
struct stack *prev;
}stack;
stack *push(stack **sp, int data)
{
stack *new = malloc(sizeof(*new));
if(new)
{
new -> prev = *sp;
new -> data = data;
*sp = new;
}
return new;
}
int isempty(stack *sp)
{
return !stack_pointer;
}
int pop(stack **sp)
{
stack *new;
int result = 0;
if(sp && *sp)
{
result = (*sp) -> data;
new = (*sp) -> prev;
free(*sp);
*sp = new;
}
return result;
}
int main(void)
{
stack *stack_pointer = NULL;
int result;
push(&stack_pointer, 1);
push(&stack_pointer, 2);
push(&stack_pointer, 3);
do
{
result = pop(&stack_pointer);
printf("%d\n", result);
}while(stack_pointer) ;
printf("Stack was empty so the loop has exited\n");
}
I have a program in C that creates a hash table.
memset is Okay but, i want to initialize with for loop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HSZ 127
#define HASHING(x) ((x)%HSZ)
struct node_t{
int val;
struct node_t *next;
};
struct node_t *hash_table[HSZ];
void init(void){
int i;
//memset(hash_table,0,sizeof(hash_table));
for(i=0; i<HSZ; i++){
hash_table[i]->val = 0;
hash_table[i]->next = NULL;
}
}
void insert_hash(int value){
int key = HASHING(value);
struct node_t *newNode = (struct node_t*)malloc(sizeof(struct node_t));
newNode->val = value;
newNode->next = NULL;
if(hash_table[key] == NULL){
hash_table[key] = newNode;
} else {
newNode->next = hash_table[key];
hash_table[key] = newNode;
}
}
int delete_hash(int value){
int key = HASHING(value);
if (hash_table[key] == NULL)
return 0;
struct node_t *delNode = NULL;
if (hash_table[key]->val == value){
delNode = hash_table[key];
hash_table[key] = hash_table[key]->next;
} else {
struct node_t *node = &hash_table[key];
struct node_t *next = hash_table[key]->next;
while (next){
if (next->val == value){
node->next = next->next;
delNode = next;
break;
}
node = next;
next = node->next;
}
}
return 1;
free(delNode);
}
void PrintAllHashData()
{
printf("###Print All Hash Data###\n");
for (int i = 0; i < HSZ; i++){
if (hash_table[i] != NULL){
printf("idx : %d ", i);
struct node_t *node = hash_table[i];
while (node->next){
printf("%d ", node->val);
node = node->next;
}
printf("%d\n", node->val);
}
}
}
int main(void){
init();
insert_hash(1);
insert_hash(3);
insert_hash(128);
PrintAllHashData();
}
look at this code.
for(i=0; i<HSZ; i++){
hash_table[i]->val = 0;
hash_table[i]->next = NULL;
}
The IDE I am using does not throw up a compilation error when I compile the code, but during the execution the code faults and is terminated/haulted. I tried debugging the code, it faults at this line and is stopped, I think BAD ACCESS points to Segmentation Error.
then, I changed this line to
for(i=0; i<HSZ; i++){
hash_table[i].val = 0;
hash_table[i]->next = NULL;
}
but, then I got the compilation error stating 'structure type require instead of 'struct node_t *'
I think that I don't understand clearly about struct in C.
How to fix this problem?
What you are dealing with is Undefined Behavior.
See, struct node_t *hash_table[HSZ];
So, hash_table is an array of HSZ (127) pointers of the data type struct node_t.
When you do,
for(i=0; i<HSZ; i++){
hash_table[i]->val = 0;
hash_table[i]->next = NULL;
}
hash_table[0] to hash_table[126] pointers are not pointing to anything.
So, each of them (or all of them) should be initialized first to point to an object of the type struct node_t and then you can initialize them. For that matter, Using a memset does not cause a problem because memset is filling the contents of the pointers with all zeros. There is difference between filling the pointers with all zeros and filling all zeros to the memory pointed by pointers.
Trying this,
for(i=0; i<HSZ; i++){
hash_table[i].val = 0;
hash_table[i]->next = NULL;
}
is plain wrong.
To fix the issue you are facing, you need to allocate memory dynamically using malloc. You can do the in your for loop.
for(i = 0; i < HSZ; i++)
{
//Allocate memory of the size struct_node_t
hash_table[i] = malloc(sizeof(struct node_t)); //Do not cast!
//Check if memory is allocated
if(hash_table[i] == NULL)
{
//Memory not allocated, set some error state to handle and break
break;
}
//Initialize to zero
hash_table[i]->val = 0;
hash_table[i]->next = NULL;
}
struct node_t{
int val;
struct node_t *next;
};
struct node_t *hash_table[HSZ];
when you have *hash_table[HSZ], this varible hash_table is a pointer. so whatever your action is , use hash_table-> ,syntax for pointer, mean point to somewhere.
a suggestion that when you use pointer you should always allocate memory hash_table[i] = malloc(sizeof(struct node_t));
struct node_t hash_table;
but if you initilize your varible like this, you can use hash_table.val = 0
so the way of assign value depend on how you declare your varibles
struct node_t *hash_table[HSZ];
gives you an array of pointers that are unset (i.e. not pointing to anything)
void init(void) {
int i;
// memset(hash_table,0,sizeof(hash_table));
for (i = 0; i < HSZ; i++) {
hash_table[i]->val = 0;
hash_table[i]->next = NULL;
tries writing to your invalid pointers which gives undefined behavior.
Either make the array an array of structs (instead of pointers):
struct node_t hash_table[HSZ];
...
/* note use of . instead of -> since we have structs not pointers */
hash_table[i].val = 0;
or allocate the necessary structs so the array points to something:
for (i = 0; i < HSZ; i++) {
hash_table[i] = malloc(sizeof(struct node_t));
hash_table[i]->val = 0;
hash_table[i]->next = NULL;
}
typedef struct mensagem
{
int sender ;
int receiver ;
char *text ;
} *Item ;
typedef struct node
{
Item item ;
struct node *next ;
} *link ;
link init(char* text)
{
link x = (link) malloc(sizeof(struct node));
(x->item->text) = (char*) malloc(sizeof(char)*(strlen(text)+1));
strcpy(x->item->text, text);
x->next = NULL;
return x;
}
I meant to use the data inside item, but I get a Segmentation Fault on the line:
(x->item->text) = (char*) malloc(sizeof(char)*(strlen(text)+1));
I'm fairly new to C and pointers, but I can't find the problem here.
You haven't allocated memory for the structure pointed to by x->item. Add
x->item = malloc(sizeof (struct mensamam));
before the other malloc.
Put this after allocating memory for x:
x->item = malloc(sizeof(struct mensagem));
You have to allocate the memory for the field 'item' before you can actually access and allocate its fields.
This should do just fine:
typedef struct mensagem
{
int sender ;
int receiver ;
char *text ;
} Item ;
typedef struct node
{
Item *item ;
struct node *next ;
} Link ;
Link *init(char *text)
{
// Note: Do error checking after each of these lines in case malloc() fails!
Link *x = malloc(sizeof(Link));
x->item = malloc(sizeof(Item));
x->item->text = malloc(sizeof(char) * (strlen(text) + 1));
strcpy(x->item->text, text);
x->next = NULL;
return x;
}
I trying to write a queue(String Version) program in C by using linked lists.
Here is the structure:
struct strqueue;
typedef struct strqueue *StrQueue;
struct node {
char *item;
struct node *next;
};
struct strqueue {
struct node *front;//first element
struct node *back;//last element in the list
int length;
};
I creates a new StrQueue first
StrQueue create_StrQueue(void) {
StrQueue q = malloc(sizeof (struct strqueue));
q->front = NULL;
q->back = NULL;
q->length = 0;
return q;
}
makes a copy of str and places it at the end of the queue
void push(StrQueue sq, const char *str) {
struct node *new = malloc(sizeof(struct node));
new->item = NULL;
strcpy(new->item,str);//invalid write size of 1 ?
new->next = NULL;
if (sq->length == 0) {
sq->front = new;
sq->back = new;
} else {
sq->back->next = new;
sq->back = new;
}
sq->length++;
}
frees the node at the front of the sq and returns the string that was first in the queue
char *pop(StrQueue sq) {
if (sq->length == 0) {
return NULL;
}
struct node *i = sq->front;
char *new = sq->front->item;
sq->front = i->next;
sq->length --;
free(sq->front);
return new;
}
I got invalid write size of 1 at strcpy(new->item,str); I dont understand why I got this error.
Can anyone tell me why and tell me how should I fix it? Thanks in advance.
Okay, first things first, in the answer below I am NOT fixing your doubly linked list concepts, I am just showing you how you should fix the code above within the scope of your question. You may want to look into how doubly linked lists are done.
In:
void push(StrQueue sq, const char *str) {
struct node *new = malloc(sizeof(struct node));
new->item = NULL;
The next statement is wrong:
strcpy(new->item,str);
There are two ways you can solve it:
Make sure that *str is a valid pointer outside of the list management context while the list is being used.
Let the list manage the string allocation (and possibly deallocation).
is the quick and dirty method, it's easier to debug later but larger codebase makes it cumbersome.
cleaner looking code, but requires initial setup discipline, you should create object (string) management routines in addition to list management routines. can be cumbersome in its own right.
CASE 1: const char *str is guaranteed to be valid for life of StrQueue (this is what you are looking for really)
It should be:
new->item = str;
Here we assume str was a dynamic string allocated elsewhere
Now, in pop when you pop off the string you are okay. because the pointer you are returning is still valid (you are guaranteeing it elsewhere)
CASE 2: const char *str is not guaranteed to be valid for life of StrQueue
Then use:
new->item = strdup(str);
Now, in pop when you pop off the string you can either
de-allocate the strdup and not return anything, (not quite the same things as you did)
pass a container pointer to pop where contents of item are copied (clean)
return the popped off pointer, but you must deallocate it separately when you are done with it (ugly)
Which would make your pop function one of the following:
Case 2.1:
void pop(StrQueue sq) {
if (sq->length == 0) {
return NULL;
}
struct node *node = sq->front;
sq->front = node->next;
sq->length--;
free(node->item);
free(node);
}
Case 2.2:
char *pop(StrQueue sq, char *here) {
if (sq->length == 0) {
return NULL;
}
struct node *node = sq->front;
sq->front = node->next;
sq->length--;
strcpy(here, node->item);
free(node->item);
free(node);
}
Case 2.3:
char *pop(StrQueue sq) {
char *dangling_item = NULL;
if (sq->length == 0) {
return NULL;
}
struct node *node = sq->front;
sq->front = node->next;
sq->length--;
dangling_item = node->item;
free(node);
return dangling_item;
}
I got invalid write size of 1 at strcpy(new->item,str); I dont understand why I got this error. Can anyone tell me why and tell me how should I fix it?
Why:
This code:
new->item = NULL;
strcpy(new->item,str);//invalid write size of 1 ?
You're not suppose to pass a null pointer to the first argument, it should be a pointer to allocated memory. The reason why you're getting this error message, I can imagine, is because the implementation of strcpy probably looks like this:
for (int i = 0; str2[i]; i++) str1[i] = str2[i];
And in the first iteration of the for loop, it writes to address 0 (a read-only section of memory) - this gives you the invalid write of size 1. I'm not sure, however, why you are only getting a size of 1, though (I would imagine it would be the entire size of the string). This could be because either a) str is only of size 1 or b) because the signal, SIGSEGV stops the program.
How to fix:
Allocate space for new->item before calling strcpy, like this:
new->item = malloc (strlen (str) + 1); // + 1 for null-terminating character
But you could probably include some error checking, like this:
int len = strlen (str) + 1;
if (len){
new->item = malloc (len);
if (!new->item){
return;
}
}
I'm getting a segmentation fault when I do free() in the delete function of the following linked list implementation. Please take a look and tell me where I am going wrong. When I run this program with valgrind, there is no seg. fault, it runs fine. So I am not able to figure out the problem.
typedef struct node {
char name[100];
int id;
struct node* next;
} Node;
void insert(Node** p, char* _name, int _id)
{
Node *temp, *prev;
temp = malloc(sizeof(struct node));
temp->next = NULL;
strcpy(temp->name,_name);
temp->id = _id;
if(*p == NULL) {
*p = temp;
}
else {
for(prev = *p; prev->next!=NULL; prev=prev->next);
prev->next=temp;
}
}
/* Delete entry
#params p first element
_id ID to delete
*/
void delete_by_id(Node** p, int _id) {
Node *temp, *prev;
prev = NULL;
for(temp = *p; temp!= NULL; prev = temp, temp=temp->next) {
if(temp->id == _id) {
printf("Deleting entry with id: %d\n", temp->id);
if(prev == NULL)
*p = temp->next;
else
prev->next= temp->next;
free(temp);
return;
}
}
}
Here is part of the code from the main program:
Node* p;
int main() {
...
...
buf[rval]=0;
char* tokens = strtok(buf, "+");
char* strArray[5]; /* up-to 5 words can be stored */
int n = 0;
while (tokens)
{
strArray[n] = malloc(strlen(tokens) + 1);
strcpy(strArray[n++], tokens);
tokens = strtok(NULL, "+");
}
int type = 0;
if(strcmp(strArray[0], "1") == 0)
type = 1;
else
type = 2;
char* name = "";
if(type == 1) {
name = strArray[1];
insert(&p, name, clients[i]);
display(&p);
} else {
name = strArray[1];
rval = search(&p, name);
if(rval) {
delete_by_id(&p, rval);
display(&p);
}
}
for (i = 0; i < 5; i++)
{
if (strArray[i]) // check for null data
free(strArray[i]);
}
...
...
}
int search(Node** p, char* _name) {
Node *temp;
for (temp = *p; temp!= NULL; temp = temp->next) {
if (strcmp((char *)temp->name, _name)==0) {
printf("Name matched: %s\n", temp->name);
return temp->id;
}
}
return 0;
}
Valgrind is complaining about the malloc and free used for strArray but not for the linked list.
Print out the addresses returned by malloc(), and also print out the value of temp immediately before the call to free(). Make sure that what's being passed to free() matches what you expect. If somehow you are passing a pointer to free() that didn't come from malloc(), you can encounter problems like you are seeing.
There's also a possibility that the function delete_by_id() is using an invalid pointer. The p parameter is dereferenced before it's checked for NULL. I recommend walking through the function in your debugger and making sure that all of the pointers look as you expect them to look.
Let your program dump core and analyze the core in GDB:
gdb -c yourprog.core yourprog
then do a full backtrace:
(gdb) bt full
This will show you where exactly the reason for your segfault is and what values were passed to the function.
(edit) Oh, and compile your program with the GCC -g switch to have debugging information.
Run your program through valgrind. Segfaults on free are usually due to writes outside of the allocated memory (which overwrites/corrupts the wrappers that the system places before/after allocated memory). Valgrind is usually the easiest way to find out when the writes in question happens.