C Linked List/Stack w/ void data members issue - c

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));

Related

How can I test this function which erases off the list all elements, whose data is "equal" to the reference data

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

Segmentation Fault 11: 10

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.

Adding node to global linked list causing crash

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.

Why is memory being leaked in my C reverse list function?

I'm fairly new to Pointers and the memory model so excuse me if this is obvious, but I am writing a program to test a function reverse that reverses a list. Anyway I have it in three files, C5.c, C5-driver.c, and C5.h. Here they are in that order:
#include "C5.h"
#include <stdlib.h>
#include <stdio.h>
struct node *cons(int fst, struct node *rst) {
struct node *new = malloc(sizeof(struct node));
if (new == NULL) {
printf("cons: out of memory\n");
abort();
}
(*new).first = fst; /* same as (*new).first = fst */
(*new).rest = rst;
return new;
}
struct node *reverse(struct node *lst) {
struct node *ans = NULL;
while (lst != NULL) {
ans = cons((*lst).first, ans);
lst = (*lst).rest;
}
return ans;
}
void free_list(struct node *lst) {
struct node *p;
while (lst != NULL) {
p = lst->rest;
free(lst);
lst = p;
}
}
void print_list(struct node *lst) {
printf("( ");
while (lst != NULL) {
printf("%d ", (*lst).first);
lst = (*lst).rest;
}
printf(")\n");
}
C5-driver.c
#include <stdlib.h>
#include <stdio.h>
#include "C5.h"
int main() {
struct node *lst1 = cons(5, NULL);
struct node *lst2 = cons(3, lst1);
struct node *lst3 = cons(1, lst2);
print_list(lst3);
lst3 = reverse(lst3);
print_list(lst3);
free_list(lst3);
}
C5.h
struct node {
int first;
struct node *rest;
};
struct node *cons(int ,struct node *);
struct node *reverse(struct node *);
void print_list(struct node *);
void free_list(struct node *);
However I'm told by XCode that there are memory leaks.
I'm assuming it's after cons is used however I've tried creating a new struct node *ans = new and free(new); with return ans; but that doesn't work. I've also tried free_list as you can see above.
Thanks~
The reverse function calls cons which allocates memory, then it overwrites the lst3 pointer. The memory leak is that lst3 is overwritten which makes it impossible to recover that memory.
You should probably make a new variable like struct node *lst3_reverse and lst3_reverse = reverse(lst3). Then you can safely do free_list(lst3) and free_list(lst3_reverse) to free the memory.

C linked list push function, just checking if this is correct

So I'm just wondering if this push function, which pushes a new value to the top a linked list stack is correct
void push(node** hd, int v){
node temp;
temp = (node*)malloc(sizeof(node));
temp -> val = v;
temp -> next = *hd;
*hd = temp;
}
Thanks in advance!
Also I'm wondering how I would make a pop function, to pop the most recently pushed value off of the stack.
The struct code looks like this by the way...
typedef struct nodeStruct
{
int val;
struct nodeStruct* next;
}node;
typedef node* list;
Dont define pointer types. They are confusing. Define a normal type and dereference it explicitly. Here is what you were trying to do without the pointer types.
#include <stdlib.h>
#include <stdio.h>
typedef struct nodeStruct
{
int val;
struct nodeStruct *next;
} node;
static void push(node **head, int v)
{
node *temp = malloc(sizeof(node));
temp->val = v;
temp->next = *head;
*head = temp;
}
int main(int argc, char **argv)
{
(void) argv;
(void) argc;
node *list = NULL;
for (int i=0; i<10; ++i) {
push(&list, i);
}
for(node *l = list; l != NULL; l = l->next) {
printf("%d ", l->val);
}
printf("\n");
return 0;
}
Note that you should check for failure of malloc. In other words, malloc can return NULL, which should be handled - left to you.

Resources