Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I made this program in c to reverse stack. but it is crashing. please help me figure out what is wrong. the program is working fine till taking inputs. but when reverse is called it crashes. i am not able to find the fault. all the memory is being allocated properly. so i dont think there is segmentation fault.
#include<stdio.h>
#include<stdlib.h>
typedef struct Node{
int data;
struct Node *next, *prev;
}SNode;
typedef struct{
SNode *top;
int count;
}Stack;
int isEmpty(Stack *s){
return (s->count==0);
}
void push(Stack *s,int x){
SNode *temp = (SNode *)malloc(sizeof(SNode));
temp->next = s->top;
temp->prev = NULL;
s->top->prev = temp;
temp->data = x;
s->top = temp;
s->count++;
}
int pop(Stack *s){
if(isEmpty(s)){
printf("Underflow");
return;
}
SNode *temp = s->top;
s->top = s->top->next;
s->top->prev = NULL;
int a = temp->data;
free(temp);
s->count--;
return a;
}
void reverse(Stack *s,Stack *rs){
while(!isEmpty(s)){
int p = pop(s);
push(rs,p);
}
}
int main(){
Stack *s = (Stack *)malloc(sizeof(Stack));
Stack *rs = (Stack *)malloc(sizeof(Stack));
char p='y';
while(p=='y'){
int pu;
printf("Enter data to be pushed: ");
scanf(" %d",&pu);
push(s,pu);
printf("Do you want to push another number? y/n:");
scanf(" %c",&p);
}
reverse(s,rs);
printf("Top of reversed stack: %d",rs->top->data);
return 0;
}
I dont know what i changed. i rewrote the code, this time using singly linked list, now it works really fine. dont know how !!??
#include<stdio.h>
#include<stdlib.h>
typedef struct node{
int data;
struct node *next;
}SNode;
typedef struct{
int count;
SNode *top;
}stack;
int isEmpty(stack *s){
return (s->count==0);
}
void push(stack *s,int x){
SNode *temp = (SNode *)malloc(sizeof(SNode));
temp->data = x;
temp->next = s->top;
s->top=temp;
s->count++;
}
int pop(stack *s){
if(isEmpty(s)){
printf("Underflow");
return -1;
}
SNode *temp = s->top;
s->top = temp->next;
int a = temp->data;
free(temp);
s->count--;
return a;
}
void reverseStack(stack *s, stack *rs){
while(!isEmpty(s)){
push(rs,pop(s));
}
}
int main(){
stack *s = (stack *)malloc(sizeof(stack));
stack *rs = (stack *)malloc(sizeof(stack));
s->count = rs->count =0;
char p ='y';
while(p=='y'){
int x;
printf("Enter data to push: ");
scanf("%d",&x);
push(s,x);
printf("Do you want to push more data? : y/n");
scanf(" %c",&p);
}
reverseStack(s,rs);
printf("Top of reversed stack: %d",rs->top->data);
return 0;
}
You have a number of problems in your implementation of your stack. The first of which is in push(), when you call:
temp->next = s->top;
s->top is an uninitialized pointer whose value is indeterminate. That invokes Undefined Behavior. Since this occurs on your very first call to push(s, pu), you can have zero confidence in the operation of the remainder of your code.
Next, both your push and pop function fail to test and handle in an appropriate manner whether the node being pushed or popped is the first or last node in the stack. These must be handled differently as the handling of your prev and next pointers will depend on whether other nodes exist. (you can't assign a next or prev node if you are pushing the first node, and you can't assign a new top on pop if no more nodes exist.
(note: you also seem to have used prev and next in a somewhat inconsistent manner. As long as you use them consistently, it doesn't matter whether you use prev for the existing top on push or next. I tend to have prev pointing down the stack and next pointing from the bottom up - but you are free to do it the other way)
To properly handle the first and last node in your stack, you can do a simple check on isempty() or simply check if (s->top == NULL) or if (s->count == 0).
You also need to initialize all pointers and count when you allocate storage for your stack and nodes. Failure to initialize all values on allocation will likely lead to an inadvertent attempted read from an uninitialized value (invoking additional instances of Undefined Behavior).
To eliminate that possibility, you can create simply helper functions, say create_node and create_stack to allocate, and validate the allocation, initialize the needed values, and then to provide a meaningful return indicating success or failure. You could do something simple like the following:
snode *create_node (int x)
{
snode *tmp = malloc (sizeof *tmp);
if (!tmp) {
perror ("create_node: memory exhausted.");
return NULL;
}
tmp->data = x;
tmp->prev = tmp->next = NULL;
return tmp;
}
stack *create_stack (void)
{
stack *tmp = malloc (sizeof *tmp);
if (!tmp) {
perror ("create_stack: memory exhausted.");
return NULL;
}
tmp->top = NULL;
tmp->count = 0;
return tmp;
}
Now there are no possibilities of an uninitialized value.
(Also note: while not an error, the standard coding style for C avoids the use of camelCase or MixedCase variable names in favor of all lower-case while reserving upper-case names for use with macros and constants. It is a matter of style -- so it is completely up to you, but failing to follow it can lead to the wrong first impression in some circles.)
With the helper functions defined, allocating and initializing your forward and reverse stacks in main() becomes a simple matter of:
int pu;
stack *s = create_stack();
stack *rs = create_stack();
if (!s || !rs) /* validate the return from create_stack */
return 1;
Having created your forward and reverse stack, you can then handle the first and last node cases in push() and pop() with the addition of a simple conditional as described above:
void push (stack * s, int x)
{
snode *temp = create_node (x);
if (!s->top) /* is the stack empty? */
s->top = temp;
else {
s->top->next = temp;
temp->prev = s->top;
s->top = temp;
}
s->count++;
}
and for pop(),
int pop (stack *s)
{
int x;
snode *temp;
if (isempty (s)) { /* checking empty as you did in original */
printf ("underflow");
return 0;
}
x = s->top->data;
temp = s->top;
if (s->top->prev)
s->top = s->top->prev;
s->top->next = NULL;
free (temp);
s->count--;
return x;
}
Adding a short prn_stack() function to iterate over the stack without poping and freeing the nodes, you could put together a short example program to test the push, pop and reverse as follows:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next, *prev;
} snode;
typedef struct {
snode *top;
int count;
} stack;
snode *create_node (int x)
{
snode *tmp = malloc (sizeof *tmp);
if (!tmp) {
perror ("create_node: memory exhausted.");
return NULL;
}
tmp->data = x;
tmp->prev = tmp->next = NULL;
return tmp;
}
stack *create_stack (void)
{
stack *tmp = malloc (sizeof *tmp);
if (!tmp) {
perror ("create_stack: memory exhausted.");
return NULL;
}
tmp->top = NULL;
tmp->count = 0;
return tmp;
}
int isempty (stack *s)
{
return (s->count == 0);
}
void prn_stack (stack *s)
{
snode *iter;
if (isempty(s)) {
puts ("stack empty");
return;
}
iter = s->top;
for (; iter; iter = iter->prev)
printf (" %d\n", iter->data);
}
void push (stack * s, int x)
{
snode *temp = create_node (x);
if (!s->top)
s->top = temp;
else {
s->top->next = temp;
temp->prev = s->top;
s->top = temp;
}
s->count++;
}
int pop (stack *s)
{
int x;
snode *temp;
if (isempty (s)) {
printf ("underflow");
return 0;
}
x = s->top->data;
temp = s->top;
if (s->top->prev)
s->top = s->top->prev;
s->top->next = NULL;
free (temp);
s->count--;
return x;
}
void reverse (stack * s, stack * rs)
{
while (!isempty (s))
push (rs, pop (s));
}
int main ()
{
int pu;
stack *s = create_stack();
stack *rs = create_stack();
if (!s || !rs)
return 1;
while (scanf (" %d", &pu) == 1)
push (s, pu);
printf ("stack:\n");
prn_stack (s);
reverse (s, rs);
printf ("\nreversed stack:\n");
while (!isempty (rs))
printf (" %d\n", pop (rs));
free (s);
free (rs);
return 0;
}
(note: do not forget to free the memory you allocate for your forward and your reverse stacks after all the values have been popped, and always validate your memory use by using a memory-error checking program like valgrind on Linux. There are similar programs for all OS's)
Example Use/Output
$ echo "10 9 8 7 6 5 4 3 2 1" | ./bin/stack_rev
stack:
1
2
3
4
5
6
7
8
9
10
reversed stack:
10
9
8
7
6
5
4
3
2
1
To validate your memory use and that you have freed all memory you allocate and that there are no memory errors, just run your code through the memory checker, similar to the following using valgrind, e.g.
Memory Use/Error Check
$ echo "10 9 8 7 6 5 4 3 2 1" | valgrind ./bin/stack_rev
==18418== Memcheck, a memory error detector
==18418== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==18418== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==18418== Command: ./bin/stack_rev
==18418==
stack:
1
2
3
4
5
6
7
8
9
10
reversed stack:
10
9
8
7
6
5
4
3
2
1
==18418==
==18418== HEAP SUMMARY:
==18418== in use at exit: 0 bytes in 0 blocks
==18418== total heap usage: 22 allocs, 22 frees, 512 bytes allocated
==18418==
==18418== All heap blocks were freed -- no leaks are possible
==18418==
==18418== For counts of detected and suppressed errors, rerun with: -v
==18418== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Look things over and let me know if you have any further questions.
malloc doesn't initialize the struct members to zero and NULL. You have to do that yourself or use calloc instead. So change your malloc lines in your program to something like this:
Stack *s = calloc(1, sizeof(Stack));
Stack *rs = calloc(1, sizeof(Stack));
I see at least two problems.
When you malloc() a new Stack structure, you don't initialize the *top and count fields, and their contents is likely to be garbage.
In pop():
SNode *temp = s->top;
s->top = s->top->next;
s->top->prev = NULL;
What happens if the initial value of s->top->next is NULL?
Your code crashes randomly because s->count is not 0 when you first declare it in main. If you're lucky, s->count is 0, then your reverse is fine because isEmpty() will work correctly. Otherwise, you will get segmentation fault.
Related
In the example below, I created a linked list and I can add numbers successfully. However, at the
end of the execution, the function named "traverse" does not work. How can I fix this error?
Here is my code:
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
struct node
{
int data;
struct node*prev;
struct node*next;
};
void add( node*head,int number )
{
node*ptr = NULL;
if( head == NULL )
{
head = (node*)malloc(sizeof(node));
head->data = number;
head->next = NULL;
head->prev = NULL;
ptr = head;
}
else
{
ptr->next = (node*)malloc(sizeof(node));
ptr->next->prev = ptr;
ptr = ptr->next;
ptr->data = number;
ptr->next = NULL;
}
}
void traverse( node* head )
{
while( head != NULL )
{
printf("%d ",head->data);
head = head->next;
}
}
int main( void )
{
node *head = NULL;
int number;
char response;
printf("%s\n","Do you want to enter a number in linked list(y/n)?" );
scanf("%c",&response);
while( response == 'y' || response == 'Y' )
{
printf("\nEnter num..> ");
scanf("%d",&number);
add(head,number);
printf("%s\n","Do you want to continue(y/n)?" );
response = getche();
}
printf("\nYour doubly linked list\n");
traverse(head);
getch();
return 0;
}
when "traverse" is called, the console print space like the following image.
If you have decided on C, then continuing from the comments, you are attempting to update a local copy of the pointer head in add(). As mentioned, you have two option, either change the return type of add() to node *add() so you can return ptr and assign as the new head back in main(), or pass the address of head as the first parameter and update the node stored at the original pointer address in add().
You can pass the address of head to add() as follows:
void add (node **head, int number)
{
node *ptr = malloc (sizeof *ptr);
if (!ptr)
return;
ptr->data = number; /* initialized new node data */
ptr->prev = ptr->next = NULL; /* initialized both pointers NULL */
if ( *head != NULL ) { /* if not 1st node */
(*head)->prev = ptr; /* Forward-Chain new node */
ptr->next = *head;
}
*head = ptr; /* set head = new node */
}
(note: since you pass the address of head as a parameter, you must remove one level of indirection from the pointer-to-pointer in add() by dereferncing head (e.g. *head) in order to update the node at the original pointer address. You also need to use the (*head) when further derferencing the pointer with -> due to C operator precedence -- so you get the original pointer address before -> is applied)
Note, the add() function uses a method call Forward-Chaining to add each node to the list in O(1) time. This also means the list will hold the numbers in the reverse order they were entered (last first). You have two options to insert in-order, (1) iterate to the end of the list each time and add a new end node (highly inefficient for large lists, no longer O(1) time, or (2) use another tail pointer that always points to the last node to allow in-order insertions in O(1) time.
You would then call your add() function in main() with
add (&head, number);
Do NOT make things difficult on yourself when testing your list implementation. There is no reason to have to type 'y' then a number and 'y' again before every number you add to your list (that would drive me nuts...). Just add numbers to your list with a loop, you can do input later, e.g.
int main (void)
{
node *head = NULL; /* list pointer initialized NULL */
for (int i = 0; i < 20; i++) /* just add 20 nodes to list */
add (&head, i + 1);
traverse (head);
delete_list (head);
head = NULL;
/* hold terminal open on windows only */
#if defined (_WIN32) || defined (_WIN64)
getchar();
#endif
}
(note: conio.h has been removed and getchar() used to hold the terminal open on windows. Since I'm on Linux, the final getchar() is not compiled as part of my executable)
Your traverse() function will work, but get in the habit of using a separate separate pointer to iterate over you list. This isn't always required, and isn't needed in traverse() since you can use the local copy of head, but always using a temporary pointer to iterate with leave you with the original head address if you need it for use later in your function, e.g.
void traverse (const node *head)
{
const node *iter = head; /* optional, but good practice */
while (iter) {
printf ("%d ", iter->data);
iter = iter->next;
}
putchar ('\n');
}
Notice also the delete_list() function added to free() all memory added for your list. You won't always be declaring lists in main() where the memory is freed on exit. Get in the habit of keeping track of the memory you allocate and freeing the memory before your pointer goes out of scope (otherwise, you will create a memory leak)
The full program would be:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *prev, *next;
} node;
void add (node **head, int number)
{
node *ptr = malloc (sizeof *ptr);
if (!ptr)
return;
ptr->data = number; /* initialized new node data */
ptr->prev = ptr->next = NULL; /* initialized both pointers NULL */
if ( *head != NULL ) { /* if not 1st node */
(*head)->prev = ptr; /* Forward-Chain new node */
ptr->next = *head;
}
*head = ptr; /* set head = new node */
}
void traverse (const node *head)
{
const node *iter = head; /* optional, but good practice */
while (iter) {
printf ("%d ", iter->data);
iter = iter->next;
}
putchar ('\n');
}
void delete_list (node *head)
{
node *iter = head;
while (iter) {
node *victim = iter;
iter = iter->next;
free (victim);
}
}
int main (void)
{
node *head = NULL; /* list pointer initialized NULL */
for (int i = 0; i < 20; i++) /* just add 20 nodes to list */
add (&head, i + 1);
traverse (head);
delete_list (head);
head = NULL;
/* hold terminal open on windows only */
#if defined (_WIN32) || defined (_WIN64)
getchar();
#endif
}
Example Use/Output
$ ./bin/llmess
20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
Memory Use/Error Check
In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
It is imperative that you use a memory error checking program to ensure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.
For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.
$ valgrind ./bin/llmess
==16661== Memcheck, a memory error detector
==16661== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==16661== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==16661== Command: ./bin/llmess
==16661==
20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
==16661==
==16661== HEAP SUMMARY:
==16661== in use at exit: 0 bytes in 0 blocks
==16661== total heap usage: 21 allocs, 21 frees, 1,504 bytes allocated
==16661==
==16661== All heap blocks were freed -- no leaks are possible
==16661==
==16661== For counts of detected and suppressed errors, rerun with: -v
==16661== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Always confirm that you have freed all memory you have allocated and that there are no memory errors.
Look things over and let me know if you have further questions.
I have written a code in C language to implement a stack using LinkedList algorithm. Here is the code........
#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
struct listNode {
int data;
struct listNode *next;
};
struct stack{
struct stack *top;
};
struct stack *createstk(){
struct stack *stk;
stk=malloc(sizeof(struct stack));
stk->top=NULL;
return stk;
}
void push(struct stack *stk,int data){
struct listNode *temp;
temp=malloc(sizeof(struct listNode));
if(!temp){
printf("heap overflow");
return;
}
temp->data=data;
temp->next=stk->top;
stk->top=temp;
}
int pop(struct stack *stk){
if(isEmpty(stk))
return INT_MIN;
int data;
struct listNode *temp;
temp= stk->top;
stk->top=stk->top->next;
data=temp->data;
delete(temp);
return data;
}
int peek(struct stack *stk){
if(isEmpty(stk))
return INT_MIN;
return stk->top->data;
}
int isEmpty(struct stack *stk){
return stk->top==NULL;
}
void deleteStack(struct stack *stk){
struct listNode *temp,*p;
p=stk->top;
while(p){
temp=p->next;
p=p->next;
free(temp);
}
free(stk);
}
int main(){
int i=0;
struct stack *stk=createstk();
for(i=0;i<=10;i++)
push(stk,i);
printf("Top Element is %d",peek(stk));
for(i=0;i<=10;i++){
printf("popped element is %d",pop(stk));
}
if(isEmpty(stk))
printf("stack is empty");
else
printf("stack is not empty");
deleteStack(stk);
return 0;
}
[warning]assignment from incompatible pointer type.
As you can see above in the picture. I am a newbie in coding world and facing this error first time. That's why I don't know what to do. Please tell me...
The field top in the type stack has the wrong type. Change
struct stack {
struct stack *top;
};
to
struct stack {
struct listNode *top;
};
Your have a large number of error beginning with the incorrect type for stack->top, as correctly noted by August Karlstrom your type for the member top must be struct listNode *top;, e.g.
struct stack {
struct listNode *top;
};
Following the correction, you must either reorder your functions or provide function prototypes for isEmpty() and deleteStack(). Moving them up in your code before before their first use will solve the problem, e.g.
struct stack *createstk()
{
struct stack *stk;
stk = malloc (sizeof (struct stack));
stk->top = NULL;
return stk;
}
int isEmpty (struct stack *stk)
{
return stk->top == NULL;
}
void deleteStack (struct stack *stk)
{
struct listNode *temp, *p;
p = stk->top;
while (p) {
temp = p->next;
p = p->next;
free (temp);
}
free (stk);
}
...
Next, this is C, not C++ there is no delete function to free memory, so in pop(), you must call free (temp); instead of delete (temp);.
Finally, provide spacing to make your code readable. Incorporating the above, you could do the following:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
struct listNode {
int data;
struct listNode *next;
};
struct stack {
struct listNode *top;
};
struct stack *createstk()
{
struct stack *stk;
stk = malloc (sizeof (struct stack));
stk->top = NULL;
return stk;
}
int isEmpty (struct stack *stk)
{
return stk->top == NULL;
}
void deleteStack (struct stack *stk)
{
struct listNode *temp, *p;
p = stk->top;
while (p) {
temp = p->next;
p = p->next;
free (temp);
}
free (stk);
}
void push (struct stack *stk, int data){
struct listNode *temp;
temp = malloc (sizeof *temp);
if (!temp) {
perror ("push()-malloc-temp");
return;
}
temp->data = data;
temp->next = stk->top;
stk->top = temp;
}
int pop(struct stack *stk){
int data;
struct listNode *temp;
if (isEmpty(stk))
return INT_MIN;
temp = stk->top;
data = temp->data;
stk->top = stk->top->next;
free (temp);
return data;
}
int peek(struct stack *stk){
if(isEmpty(stk))
return INT_MIN;
return stk->top->data;
}
int main (void) {
int i=0;
struct stack *stk=createstk();
for (i = 0; i <= 10; i++)
push(stk,i);
printf("Top Element is %d\n",peek(stk));
for (i = 0; i <= 10; i++)
printf (" popped element is %d\n",pop(stk));
if (isEmpty(stk))
printf ("stack is empty\n");
else
printf ("stack is not empty\n");
deleteStack(stk);
return 0;
}
Example Use/Output
$ ./bin/stack_ll
Top Element is 10
popped element is 10
popped element is 9
popped element is 8
popped element is 7
popped element is 6
popped element is 5
popped element is 4
popped element is 3
popped element is 2
popped element is 1
popped element is 0
stack is empty
Memory Use/Error Check
In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
It is imperative that you use a memory error checking program to insure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.
For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.
$ valgrind ./bin/stack_ll
==25935== Memcheck, a memory error detector
==25935== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==25935== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==25935== Command: ./bin/stack_ll
==25935==
Top Element is 10
popped element is 10
popped element is 9
popped element is 8
popped element is 7
popped element is 6
popped element is 5
popped element is 4
popped element is 3
popped element is 2
popped element is 1
popped element is 0
stack is empty
==25935==
==25935== HEAP SUMMARY:
==25935== in use at exit: 0 bytes in 0 blocks
==25935== total heap usage: 12 allocs, 12 frees, 184 bytes allocated
==25935==
==25935== All heap blocks were freed -- no leaks are possible
==25935==
==25935== For counts of detected and suppressed errors, rerun with: -v
==25935== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Always confirm that you have freed all memory you have allocated and that there are no memory errors.
If you have any further questions, just let me know.
#define MAXL 256
First pass: in = "25 7 * 14 - 6 +"; run smoothly with correct answer.
Second pass: in = "1 24 3 + * 41 -"; program stopped right after outputting Num got in: 41 Expected: continue loop and get in the minus sign then pop(s) and subtract 41
I'm guessing that my program ran out of allocated space because of the free() didn't do their job as I expected but I'm not sure.
Any help would be greatly appreciated. Thank you!
double evaluatePost(char * in)
{
double * op1 = NULL, * op2 = NULL, * msgr = NULL;
int i, j;
char * c = {0}, tempExp[MAXL] = {0};
char ** token = NULL;
Stack * s = createStack();
strcpy(tempExp, in); /* Copy in to a temporary array so strtok will not destroy in */
for(c = strtok(tempExp, " "); c != NULL; ++i, c = strtok(NULL, " "))
{
if(isdigit(c[0]))
{
printf("\nNum got in: %s\n", c); /* Crash right after this line output 41 */
system("PAUSE");
msgr = (double*)malloc(sizeof(double)); /* I made a malloc check here, it never showed error */
*msgr = atoi(c); /* I don't know if it crash at this line or the next one */
push(s, msgr); /* stack has no limit, receives stack* and void* */
/* It never got pass to here after output 41 */
}
else
{
op2 = (double *)pop(s);
op1 = (double *)pop(s);
printf("\n%f %f %s\n", *op1, *op2, c);
system("PAUSE");
msgr = (double*)malloc(sizeof(double));
if(!msgr)
{
printf("Memory allocation failed.\n");
system("PAUSE");
exit(1);
}
switch(*c)
{
case '+': *msgr = (*op1 + *op2); break;
case '-': *msgr = (*op1 - *op2); break;
case '*': *msgr = (*op1 * *op2); break;
case '/': *msgr = (*op1 / *op2); break;
}
printf("\n%.1f\n", *msgr);
system("PAUSE");
/* Free the memory before they become orphans */
free(op1), free(op2);
push(s, msgr);
}
}
returnVal = *((double *)pop(s));
makeEmpty(s);
return returnVal;
}
void push(Stack * stack, void * dataInPtr)
{
/* Define a new StackNode */
StackNode * newPtr;
/* Get some Memory */
newPtr = (StackNode*)malloc(sizeof(StackNode));
if(!newPtr)
{
printf("Out of memory");
system("PAUSE");
exit(1);
}
/* Assign dataIn to dataPtr */
newPtr->dataPtr = dataInPtr;
/* Make the links */
newPtr->link = stack->top; /* Point both to top */
stack->top = newPtr; /* newPtr at top pointed to be head */
(stack->count)++;
}
void * pop(Stack * stack)
{
/* Hold the data */
void * dataOutPtr;
StackNode * temp;
/* Check if stack is empty */
if(stack->count == 0)
dataOutPtr = NULL;
else
{
/* Get the data and remove the node */
temp = stack->top; /* temp points to top */
dataOutPtr = stack->top->dataPtr; /* dataOutPtr has data */
stack->top = stack->top->link; /* stack moves to next node */
temp->link = NULL; /* break top node off stack */
free(temp); /* frees memory */
(stack->count)--;
}
return dataOutPtr;
}
typedef struct node
{
void * dataPtr;
struct Node * link;
} StackNode;
typedef struct
{
int count;
StackNode * top;
} Stack;
Your problem may lie here:
You are freeing the Stack node in pop()
temp = stack->top; /* temp points to top */
dataOutPtr = stack->top->dataPtr; /* dataOutPtr has data */
stack->top = stack->top->link; /* stack moves to next node */
temp->link = NULL; /* break top node off stack */
free(temp); /* frees memory */
And after that you are freeing the data pointer in the node in evaluatePost():
free(op1), free(op2);
The sequence freeing the memory should always be in reverse order of malloc i.e. you should allocate Node first and then node data and for freeing free the node data first, and then Node itself.
You are facing problem with some input and not with some other input, because this is undefined behavior.
To know more about undefined behavior in C, you can search for related questions in SO.
You can easily add the ability to traverse over all the nodes in your stack without freeing them. This comes in handy, if say, after pushing all nodes you need to use the collection and don't want to pop and free the data, or if you need to update the nodes in some way before popping them. All you need to do is add a single tail pointer to your stack which will hold the address of the first node pushed onto the stack. e.g.:
typedef struct
{
int count;
StackNode *top;
StackNode *tail;
} Stack;
Why? Since you have a StackNode->link, your data is effectively in linked-list form anyway. Adding a tail pointer that points to the first node pushed onto the stack, simply gives an easy way to know when to stop iterating over your nodes. With a few minor tweaks, you can then do what you attempted - iterate over all the nodes in your stack without having to pop/free the nodes as you do it.
Here is a short examples showing the minor tweaks needed. Also notice the cleanup removes all casts of malloc (don't do it) and a couple of cleanups on the malloc calls themselves:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node
{
void *dataPtr;
struct node *link;
} StackNode;
typedef struct
{
int count;
StackNode *top;
StackNode *tail;
} Stack;
Stack *stackcreate ()
{
Stack *s = malloc (sizeof *s);
if (!s) {
fprintf (stderr, "%s() error: memory allocation failed.\n", __func__);
exit (EXIT_FAILURE);
}
s->count = 0;
s->top = s->tail = NULL;
return s;
}
void push(Stack * stack, void * dataInPtr)
{
if (!stack) return;
/* Define a new StackNode & allocate */
StackNode *newPtr = malloc (sizeof *newPtr);
if(!newPtr)
{
fprintf (stderr, "%s() error: memory allocation failed.\n", __func__);
exit (EXIT_FAILURE);
}
/* Assign dataIn to dataPtr */
newPtr->dataPtr = dataInPtr;
newPtr->link = stack->top; /* Point both to top */
/* Make the links */
if (!stack->top)
stack->tail = newPtr;
stack->top = newPtr; /* newPtr at top pointed to be head */
(stack->count)++;
}
void * pop(Stack * stack)
{
/* Hold the data */
void * dataOutPtr;
StackNode * temp;
/* Check if stack is empty */
if(stack->count == 0)
dataOutPtr = NULL;
else
{
/* Get the data and remove the node */
temp = stack->top; /* temp points to top */
dataOutPtr = stack->top->dataPtr; /* dataOutPtr has data */
stack->top = stack->top->link; /* stack moves to next node */
temp->link = NULL; /* break top node off stack */
free(temp); /* frees memory */
(stack->count)--;
if (!stack->top) stack->tail = NULL;
}
return dataOutPtr;
}
int main (void) {
char *lines[] = { "my cat has more...",
"has lots of fleas, ",
"my dog, the lab, " };
size_t i = 0;
size_t entries = sizeof lines/sizeof *lines;
Stack *stack = stackcreate ();
for (i = 0; i < entries; i++)
push (stack, (void *)lines[i]);
printf (" \niterating over nodes in stack without popping\n\n");
StackNode *p;
for (p = stack->top; ;p = p->link) {
printf (" %s\n", (char *)p->dataPtr);
if (p == stack->tail)
break;
}
printf ("\n popping items from stack\n\n");
while (stack->top) {
printf (" %s\n", (char *)pop (stack));
}
printf ("\n");
return 0;
}
Example/Output
$ ./bin/stack_iter
iterating over nodes in stack without popping
my dog, the lab,
has lots of fleas,
my cat has more...
popping items from stack
my dog, the lab,
has lots of fleas,
my cat has more...
For a prelab (meaning it's not for a grade), I'm supposed to implement my first ever stack using linked lists. I wrote it adding only one thing to the stack just as practice, as to why it's so short. Anyway, I have no compile errors, besides it saying that "new" is uninitialized in my create_stack function. This is also where I'm getting a segmentation fault, as it's not printing out my first printf function. I am also guessing that the problem is bigger than just me initializing the stack, but this is my problem's start. Please go easy on me if it's something simple, as, like I said, it's my first time doing stacks, and thanks for your help.
#include <stdio.h>
#include <stdlib.h>
typedef struct node_{
char data;
struct node_ *next;
}node;
typedef struct stack_{
unsigned int size;
node* stack;
}stack;
stack* create_stack();
void push(stack* s, char val);
char top(stack* s);
void pop(stack*s);
int main(void) {
char value, val;
stack* new = create_stack();
printf("Enter a letter: ");
scanf("%c", &value);
push(new, value);
val = top(new);
printf("%c\n", val);
pop(new);
return 0;
}
stack* create_stack(){ //initializes the stack
stack* new;
new->size = 0;
new->stack = NULL;
return new;
}
void push(stack* s, char val) {
node* temp = (node*)malloc(sizeof(node)); //allocates
if ( temp == NULL ) {
printf("Unable to allocate memory\n");
}
else{
temp->next = s->stack;
temp->data = val;
s->stack = temp;
s->size = (s->size) + 1; //bumps the counter for how many elements are in the stack
}
}
void pop(stack* s) {
node* temp;
temp = s->stack;
s->stack = temp->next;
free(temp);
s->size = (s->size) - 1; //subtracts from counter
}
char top(stack* s) {
node* temp = s->stack;
char value = temp->data;
return value;
}
The reason it crashes is that you never allocate any memory when you create the stack. Do stack* new = malloc (sizeof(stack)); in the create_stack function.
For the future you might want to use better variable names. Using for instance using new as the name for the stack isn't that good - it isn't very descriptive plus it's a reserved keyword in several languages, C++ for example.
stack *new creates a local pointer, but it has nothing to point to yet. Since you want the stack to continue to exist after the function completes, you should allocate memory for it using malloc (and eventually free it using free).
So your create_stack function should start with:
stack* new = malloc(sizeof(stack));
An alternative would be to declare the stack as a local variable in your main function, and pass it as an argument into create_stack to initialize it:
stack new;
create_stack(&new);
After more than 10 years of having the luxury of using garbage collected languages, I am returning to C99 and obviously I am having difficulties with memory management.
I have a linked list consisting of stack items and a type Stack which points to the address of the first element of this list.
This is my code so far:
#include <stdio.h>
#include <stdlib.h>
typedef struct StackItem
{
int head;
struct StackItem* next;
} StackItem;
typedef StackItem** Stack;
StackItem* makeStackItem (int head)
{
StackItem* a = (StackItem*) malloc (sizeof (StackItem) );
a->head = head;
a->next = (StackItem*) 0;
return a;
}
Stack makeStack ()
{
Stack stack = (Stack) malloc (sizeof (StackItem*) );
*stack = (StackItem*) 0;
return stack;
}
void pushStack (StackItem* item, Stack stack)
{
item->next = *stack;
*stack = item;
}
void freeStack (Stack stack)
{
StackItem* current = *stack;
StackItem* next;
while (current != 0)
{
next = current->next;
free (current);
current = next;
}
free (stack);
}
int main ()
{
Stack stack = makeStack ();
for (int i = 0; i < 10; i++)
pushStack (makeStackItem (i), stack);
printf ("Here be dragons.\n");
freeStack (stack);
return 0;
}
My questions are:
Are the first lines of makeStack and makeStackItem sensible and
necessary?
Is the last line of freeStack sensible and necessary?
Once main returns, have I freed all the memory previously
allocated?
How can I see whether I have memory leaks or not?
Thank you very much in advance.
Are the first lines of makeStack and makeStackItem sensible and necessary? yes except for the casting malloc issue
Is the last line of freeStack sensible and necessary? yes
Once main returns, have I freed all the memory previously allocated? yes
How can I see whether I have memory leaks or not? use valgrind
I would toss the casts of 0 too.