I have been working on a post fix calculator for standard input and after working on it I ended up getting a saying segmentation fault (core dumped) it doesn't say where it occurs or what caused it and after looking for an explanation of what it means I couldn't really find anything that would help me fix it. So I decided I might as well ask here this is all of the stuff I have so far.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct stack
{
int data;
struct stack *up;
};
void push( struct stack * ptr, int value)
{
struct stack * tmp;
tmp = malloc(sizeof(value));
tmp -> data = value;
tmp -> up = NULL;
}
int pop(struct stack * ptr)
{
int value;
struct stack * tmp;
tmp = ptr;
value = tmp-> data;
ptr = tmp -> up;
free(tmp);
return value;
}
int evaluate(int argc,const char * argv[],struct stack * ptr)
{
int h;
int i;
for (i = 0; i <= argc - 1; i++)
{
if (strcmp(argv[i], "M") == 0)
{
int a = pop(ptr);
int b = pop(ptr);
h = b*a;
push(ptr,h);
}
else if (strcmp(argv[i], "A") == 0)
{
printf("%s\n", "error \0");
int a = pop(ptr);
int b = pop(ptr);
h = b+a;
push(ptr,h);
}
else if (strcmp(argv[i], "D") == 0)
{
int a = pop(ptr);
int b = pop(ptr);
h = b/a;
push(ptr,h);
}
else if (strcmp(argv[i], "S") == 0)
{
int a = pop(ptr);
int b = pop(ptr);
h = b-a;
push(ptr,h);
}
else
{
printf("%s", "Not an operator");
}
}
return pop(ptr);
}
int main(int argc, const char *argv[])
{
struct stack s;
struct stack *ptr = s.up;
evaluate(argc,argv,ptr);
return EXIT_SUCCESS;
}
In main you create struct stack s; and don't initialize it.
Then you pass s.up as the third argument of evaluate.
And evaluate eventually calls pop on s.up, which calls free on s.up. But s.up is still uninitialized, so it crashes.
It's because you are allocating the structs wrong, here
tmp = malloc(sizeof(value));
you are allocating enough space for a int value, so the code that follows invokes undefined behavior leading in your case to a segmentation fault, try it this way
tmp = malloc(sizeof(struct stack));
or
tmp = malloc(sizeof(*tmp));
also, always check the success of malloc() before dereferencing the pointer, like this
void push(struct stack *ptr, int value)
{
struct stack *tmp;
tmp = malloc(sizeof(*tmp));
if (tmp == NULL)
return;
tmp->data = value;
tmp->up = NULL;
}
Related
Basically I made a create_app() function to allocate 2 nodes in the stack, each having a pointer to an array[max]; undo() pops the last element, and before returning it, it adds it into the REDO node's array. redo() does the opposite, pops the last element in it's array, putting it into Undo's array before returning it. What did I do wrong ?
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#define EMPTY_TOS (-1)
typedef struct node *node_ptr;
struct node
{
int arr_size;
int tos;
int *arr_stack;
node_ptr next;
};
typedef node_ptr STACK;
STACK
create_app(int max)
{
STACK UNDO = (STACK) malloc(sizeof(struct node));
STACK REDO = (STACK) malloc(sizeof(struct node));
{
UNDO->arr_stack == (int *) malloc(max * sizeof(int));
REDO->arr_stack == (int *) malloc(max * sizeof(int));
if(UNDO->arr_stack != NULL){printf("Out of space!");}
else
{
UNDO->tos = EMPTY_TOS;
REDO->tos = EMPTY_TOS;
UNDO->arr_size = max;
REDO->arr_size = max;
UNDO->next = REDO;
REDO->next = UNDO;
return UNDO;
}
}
}
int
isEmpty(STACK S)
{
return(S->tos==-1);
}
int
isFull(STACK S)
{
return(S->tos>=S->arr_size-1);
}
void
push(int x, STACK S)
{
if(isFull(S)){printf("Stack full!");}
else
{
S->arr_stack[++S->tos] = x;
}
}
int
undo(STACK S)
{
if(isEmpty(S)){printf("Nothing to undo!");}
else
{
S->next->arr_stack[++S->next->tos] = S->arr_stack[S->tos];
printf("%d",S->arr_stack[S->tos--]);
}
}
int
redo(STACK S)
{
if(isEmpty(S->next)){printf("Nothing to redo!");}
else
{
int temp = S->next->arr_stack[S->next->tos];
push(S->next->arr_stack[S->next->tos], S);
S->next->tos--;
printf("%d",temp);
}
}
int main()
{
STACK app = create_app(5);
push(1,app);
push(2,app);
push(3,app);
undo(app);
undo(app);
redo(app);
redo(app);
/* Expected output: 3223 */
return 0;
}
Some small errors were in your code, like these ones in create_app() which seem like typos.
UNDO->arr_stack == (int *) malloc(max * sizeof(int));
REDO->arr_stack == (int *) malloc(max * sizeof(int));
^
|
if(UNDO->arr_stack != NULL){printf("Out of space!");}
^
|
...
and some int returning functions did not return anything in the else part which gave some warnings.
Here is the modified code, which worked fine for me
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#define EMPTY_TOS (-1)
typedef struct node* node_ptr;
struct node
{
int arr_size;
int tos;
int *arr_stack;
node_ptr next;
};
typedef node_ptr STACK;
STACK
create_app(int max)
{
STACK UNDO = (STACK) malloc(sizeof(struct node));
STACK REDO = (STACK) malloc(sizeof(struct node));
{
UNDO->arr_stack = (int *) malloc(max * sizeof(int));
REDO->arr_stack = (int *) malloc(max * sizeof(int));
if(UNDO->arr_stack == NULL){printf("Out of space!");
return NULL;}
else
{
UNDO->tos = EMPTY_TOS;
REDO->tos = EMPTY_TOS;
UNDO->arr_size = max;
REDO->arr_size = max;
UNDO->next = REDO;
REDO->next = UNDO;
return UNDO;
}
}
}
int
isEmpty(STACK S)
{
return (S->tos == -1);
}
int
isFull(STACK S)
{
return (S->tos >= S->arr_size-1);
}
void
push(int x, STACK S)
{
if(isFull(S)){printf("Stack full!");}
else
{
S->arr_stack[++S->tos] = x;
}
}
void
undo(STACK S)
{
if(isEmpty(S)){printf("Nothing to undo!");}
else
{
S->next->arr_stack[++S->next->tos] = S->arr_stack[S->tos];
printf("%d",S->arr_stack[S->tos--]);
}
}
void
redo(STACK S)
{
if(isEmpty(S->next)){printf("Nothing to redo!");}
else
{
int temp = S->next->arr_stack[S->next->tos];
push(S->next->arr_stack[S->next->tos], S);
S->next->tos--;
printf("%d",temp);
}
}
int main()
{
STACK app = create_app(5);
push(1,app);
push(2,app);
push(3,app);
undo(app);
undo(app);
redo(app);
redo(app);
/* Expected output: 3223 */
return 0;
}
Result:
3223
However, always take precaution in deallocating the memory malloced using free().
I have a question about my piece of code here: I tried to write a function, its name is take, the function can get only one int parameter and have to return back the middle number that was inserted. The function has to use in, as minimum memory as possible. I tried to use in a stack. Its my implementation. The problem is that the program doesn't return a value after the third insertion.
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
int take (int);
typedef struct stack
{
int num;
struct stack *next;
}stack;
stack first;
bool isit = true;
int counter = -1;
int main()
{
printf("%d",take(5));
printf("%d", take(6));
printf("%d", take(7));
return 0;
}
int take(int value)
{
if (isit)
{
isit = false;
first.num = value;
first.next = NULL;
}
else
{
static stack newone;
newone.num = value;
newone.next = NULL;
stack temp = first;
while (temp.next != NULL)
{
temp = *temp.next;
}
temp.next = &newone;
}
stack *temp1 = malloc(sizeof(stack));
*temp1 = first;
counter++;
if (counter > 1 && counter % 2 == 0)
{
temp1 = temp1->next;
}
return (temp1->num);
}
A big problem in your code is that you use global variables where you don't need
them. This creates problems that don't expect, like this:
int take(int value)
{
...
static stack newone;
newone.num = value;
newone.next = NULL;
stack temp = first;
while (temp.next != NULL)
{
temp = *temp.next;
}
temp.next = &newone;
The static stack newone is a static variable, it means it will be always the
same every time you call take, you are overwriting the values all the time,
specially the next pointer.
For this reason, avoid using global variables when you can perfectly declare
them in the main function and pass them to the other functions.
Also you malloc part doesn't make any sense. You want minimal memory footprint
but you allocate memory which is lost after temp1 = temp1->next;.
If you want a minimal memory footprint and not having to allocate memory with
malloc, then you can declare an array of fixed length and use it as a stack,
something like this:
typedef struct stack
{
int stack[20];
size_t len;
size_t size;
} Stack;
void stack_init(Stack *stack)
{
if(stack == NULL)
return;
stack->size = sizeof stack->stack / sizeof stack->stack[0];
stack->len = 0;
}
int stack_is_empty(Stack *stack)
{
if(stack == NULL)
return 1;
return stack->len == 0;
}
int stack_is_full(Stack *stack)
{
if(stack == NULL)
return 0;
return stack->len == stack->size;
}
int stack_push(Stack *stack, int value)
{
if(stack == NULL)
return 0;
if(stack_is_full(stack))
return 0;
stack->stack[stack->len++] = value;
return 1;
}
int stack_pop(Stack *stack, int *val)
{
if(stack == NULL)
return 0;
if(stack_is_empty(stack))
return 0;
stack->len--;
if(val)
*val = stack->stack[stack->len];
return 1;
}
int take(Stack *stack, int value)
{
if(stack == NULL)
return 0;
if(stack_push(stack, value) == 0)
fprintf(stderr, "stack is full, cannot push\n");
return stack->stack[stack->len / 2];
}
int main(void)
{
Stack stack;
stack_init(&stack);
printf("%d", take(5));
printf("%d", take(6));
printf("%d", take(7));
return 0;
}
This question already exists:
C- How can I push Strings to stack one element at a time?
Closed 7 years ago.
Currently my code uses a stack and pushes a user entered string into the stack one by one. However I would like to make it dynamic, what would I malloc/realloc, I know I'm missing something completely obvious but I guess I have tunnel vision... help?
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 100
char a [MAXSIZE];
char * p = a;
int top = -1;
void push ( char n )
{
if ( top == 99)
{
printf( "stack overflow");
return;
}
top+=1;
a[top] = n;
}
/* Function to delete an element from the stack */
void pop(){
if(top == -1)
printf("Stack is Empty");
else
top-=1;
}
char *inputString(FILE* fp, size_t size){
//The size is extended by the input with the value of the provisional
char *str;
int ch;
size_t len = 0;
str = realloc(NULL, sizeof(char)*size);//size is start size
if(!str)return str;
while(EOF!=(ch=fgetc(fp)) && ch != '\n'){
str[len++]=ch;
if(len==size){
str = realloc(str, sizeof(char)*(size+=16));
if(!str)return str;
}
}
str[len++]='\0';
return realloc(str, sizeof(char)*len);
}
int balanced (char * m){
int size = sizeof(m);
int i, j;
for (i=0; i<=size; ++i){
push(m[i]);
}
}
int main(void){
char *m;
printf("input string : ");
m = inputString(stdin, 10);
printf("%s\n", m);
balanced(m);
int i;
for (i=0;i<=sizeof(a);++i){
printf("\n%c", a[i]);
}
free(m);
return 0;
}
If I understand your question properly, this is what you are supposed to do.
struct Stack
{
char c;
struct Stack *next;
}*stack = NULL;
char pop()
{
if(stack == NULL)
{
printf("Stack Underflow\n");
return NULL;
}
c = stack -> c;
struct Stack * temp = stack;
stack = stack -> next;
free(temp);
return c;
}
void push(char c)
{
struct Stack * temp = malloc(sizeof(struct Stack));
temp -> next = NULL;
temp -> c = c;
if (stack == NULL)
stack = temp;
else
{
temp -> next = stack;
stack = temp;
}
}
I have a program that takes in strings using the command line prompts argv and argc. I keep getting a segmentation fault when I go to run the code and after much researching, I cannot determine what might be causing this. Maybe how I execute the code is the issue? I am using gcc -o code code.c then ./code one two three with one two three being the strings added to the linked list. Any assistance in determining where my error might be would be great.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct list_node_s{
char the_char;
struct list_node_s *next_node;
}list_node;
void insert_node(list_node *the_head, char the_char);
void print_list(list_node *the_head);
int main(int argc, char *argv[]){
char next_char;
list_node *the_head = NULL;
insert_node(the_head, next_char);
the_head->next_node = malloc(sizeof(list_node));
if(the_head == NULL){
return 1;
}
the_head->the_char = 1;
the_head->next_node == NULL;
int the_count, the_count2;
for(the_count = 0; the_count < sizeof(argv); the_count++){
for(the_count2 = 0; argv[the_count][the_count2] != '\0'; the_count2++){
next_char = argv[the_count][the_count2];
insert_node(the_head, next_char);
}
}
print_list(the_head);
return (0);
}
void insert_node(list_node *the_head, char the_char){
list_node * current_node = the_head;
while (current_node->next_node != NULL) {
current_node = current_node->next_node;
}
current_node->next_node = malloc(sizeof(list_node));
current_node->next_node->the_char = the_char;
current_node->next_node->next_node = NULL;
}
void print_list(list_node *the_head){
if(the_head == NULL){
printf("\n");
}else{
printf("%c", the_head->the_char);
print_list(the_head->next_node);
}
}
Change this:
list_node *the_head = NULL;
insert_node(the_head, next_char);
the_head->next_node = malloc(sizeof(list_node));
to:
list_node the_head = { '\0', NULL };
to initialize the_head to an empty node.
One problem is in this function:
void insert_node(list_node *the_head, char the_char){
list_node * current_node = the_head;
while (current_node->next_node != NULL) {
current_node = current_node->next_node;
}
current_node->next_node = malloc(sizeof(list_node));
current_node->next_node->the_char = the_char;
current_node->next_node->next_node = NULL;
}
When you call it in main you're basically passing in NULL because you're setting the_head to NULL. You're trying to access current_node->next_node in the while loop conditions, but because of what you're passing in, you're basically doing NULL->next_node.
You need to initialize your head to an empty list_node. Basically since you're using a char as your node element you could set the value of the char to 0x00, which would make it a zero byte. Then that way you know that when you're at that value, you're at the head.
I don't mean to self-promote, but if you want to look at some code for this have a look at this github repo for the Barry_CS-331 Data Structures class. There's C and C++ in there for the Data Structures. I think it might have a list but if not you can use the stack and the queue as an overall example.
I have modified you code, there has some bugs:
1)、the key bug is in this code.
for(the_count = 0; the_count < sizeof(argv); the_count++)
{
for(the_count2 = 0; argv[the_count][the_count2] != '\0'; the_count2++)
{
next_char = argv[the_count][the_count2];
insert_node(the_head, next_char);
}
}
there some bugs:
you cann't use the_count < sizeof(argv), because of the type of argv is char* []; so sizeof(argv) maybe 4 or 8, based on your os.
the right is:
for(the_count = 1; the_count < argc; the_count++){
for(the_count2 = 0; argv[the_count][the_count2] != '\0'; the_count2++){
next_char = argv[the_count][the_count2];
insert_node(the_head, next_char);
}
}
2、this code aose has some bugs:
list_node *the_head = NULL;
insert_node(the_head, next_char);
the_head->next_node = malloc(sizeof(list_node));
if(the_head == NULL){
return 1;
}
the_head->the_char = 1;
the_head->next_node == NULL;
insert_node(the_head, next_char); is no need, you'd better do the_head->the_char = '\0', because of char 1 is no printable character.
One way:
#include <stdio.h>
#include <stdlib.h>
typedef struct list_node_s{
char the_char;
struct list_node_s *next_node;
}list_node;
void insert_node(list_node *the_head, char the_char);
void print_list(list_node *the_head);
int main(int argc, char *argv[]){
list_node *the_head = NULL;
int the_count, the_count2;
for(the_count = 0; the_count < argc; the_count++)
{
for(the_count2 = 0; the_count2 < strlen(argv[the_count]); the_count2++)
insert_node(&the_head, argv[the_count][the_count2]);
}
print_list(the_head);
return (0);
}
void insert_node(list_node **the_head, char the_char){
list_node *new_node;
list_node *tail_node;
/* Allocate and populate a new node. */
new_node = malloc(sizeof(list_node));
new_node->the_char = the_char;
new_node->next_node = NULL;
/* Is the_head already initialized? */
if(*the_head)
{
/* Yes... find the tail_node. */
tail_node = *the_head;
while(tail_node->next)
tail_node = tail_node->next;
/* Append the new_node to the end of the list. */
tail_node->next = new_node;
return;
}
/* the_head was not initialized. The new_node will be the head node. */
*the_head = new_node;
return;
}
void print_list(list_node *the_head){
if(the_head == NULL){
printf("\n");
}else{
printf("%c", the_head->the_char);
print_list(the_head->next_node);
}
}
So all I'm trying to do is free a pointer and it just gives me the error 'invalid address'; though the address is clearly valid, as illustrated by the prints I put in. It tries to free the address of the pointer, but still fails. Through valgrind, it gives the error invalid free() saying the address is on thread 1's stack? The code below is runnable; can anyone help?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define SUCC 1
#define FAIL -1
typedef struct bucket {
char *key;
void *value;
struct bucket *next;
} Bucket;
typedef struct {
int key_count;
int table_size;
void (*free_value)(void *);
Bucket **buckets;
} Table;
extern unsigned int hash_code(const char *key) {
unsigned int hash = 0, i = 0;
while(i < strlen(key)) {
hash ^= ((hash << 3) | (hash >> 29)) + key[i++];
}
return hash;
}
/*Makes copy of string and returns pointer to it*/
char * cpy(const char *str) {
char *new = malloc(sizeof(char *));
if(new)
strcpy(new, str);
return new;
}
int create_table(Table ** table, int table_size, void (*free_value)(void *)) {
*table = malloc(sizeof(Table));
if(table && table_size != 0) {
int i = 0;
(*table)->key_count = 0;
(*table)->table_size = table_size;
(*table)->free_value = free_value;
(*table)->buckets = calloc(table_size, sizeof(Bucket *));
while(i < table_size)
(*table)->buckets[i++] = NULL;
return SUCC;
}
return FAIL;
}
int put(Table * table, const char *key, void *value) {
if(table && key) {
int hash = hash_code(key)%table->table_size;
Bucket *curr = table->buckets[hash];
while(curr) {
if(strcmp(curr->key, key) == 0) {
if(table->free_value)
table->free_value(curr->value);
printf("addr of ptr: %p\n", value);
curr->value = value;
printf("addr of curr ptr: %p\n", curr->value);
return SUCC;
}
curr = curr->next;
}
curr = malloc(sizeof(Bucket));
curr->key = cpy(key);
printf("addr of ptr: %p\n", value);
curr->value = value;
printf("addr of curr ptr: %p\n", curr->value);
curr->next = table->buckets[hash];
table->buckets[hash] = curr;
table->key_count++;
return SUCC;
}
return FAIL;
}
int remove_entry(Table * table, const char *key) {
if(table && key) {
int hash = hash_code(key)%(table->table_size);
Bucket *curr = table->buckets[hash], *prev = table->buckets[hash];
while(curr) {
printf("attempt");
if(strcmp(curr->key, key) == 0) {
void * test = curr->value;
printf("at addr %p\n", test);
table->free_value(test);
printf("freed");
if(table->free_value){
table->free_value(curr->value);
}
free(curr->key);
curr->key = NULL;
curr->value = NULL;
table->key_count--;
if(prev == curr)
table->buckets[hash] = curr->next;
else
prev->next = curr->next;
free(curr);
curr = NULL;
return SUCC;
}
prev = curr;
curr = curr->next;
}
}
return FAIL;
}
And the test file that shows the error:
#include <stdio.h>
#include <stdlib.h>
#include "htable.h"
int main() {
Table *t;
int num2 = 3;
printf("create: %d\n",create_table(&t, 2, free));
printf("addr of ptr: %p\n",(void *)&num2);
printf("put %s: %d\n","test",put(t, "test", &num2));
printf("rem key: %d\n",remove_entry(t, "test"));
return 0;
}
This is broken:
char *new = malloc(sizeof(char *));
The amount of memory you need is based on what you need to store, which is the string. You want:
char *new = malloc(strlen(str) + 1);
Or, better yet, just use strdup.
You are trying to free() a stack variable: num2 (in main()):
int num2 = 3;
Later, you have this call:
printf("put %s: %d\n","test",put(t, "test", &num2));
You're passing the address of num2 to put(), which means that remove_entry() will try to free it later. This is illegal. You cannot free a variable allocated on the stack. You should dynamically allocate num2 instead:
int* num2 = malloc(sizeof(int));
*num2 = 3;
There's another problem as well though. In this code:
void * test = curr->value;
printf("at addr %p\n", test);
table->free_value(test);
printf("freed");
if(table->free_value){
table->free_value(curr->value);
}
You are freeing curr->value twice, because you're freeing test which is just a copy of the pointer.