I am getting a two instances of memory leaks that I can't seem to solve. The first instance occurs from char *temp = (char*)malloc(sizeof(char*));, I use this variable at the beginning of a if statement and make sure to free it at the end, but I'm still getting a leak. The second occurs from s = create(); and s = (Stack*)malloc(sizeof(Stack));.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char **data;
int top;
int size;
}Stack;
typedef enum { FALSE, TRUE } bool;
Stack* create(){
Stack *s;
s = (Stack*)malloc(sizeof(Stack));
s->top = -1;
s->size = 10;
s->data = (char**)malloc(s->size*sizeof(char*));
return s;
}
void deleteStack(Stack* ps){
if(ps == NULL){
printf("No memory allocated in Stack.\n");
}
while(ps->top >= 0){
free(ps->data[ps->top]);
ps->top--;
}
free(ps->data);
}
bool full( Stack s){
if(s.top == s.size-1)
return TRUE;
return FALSE;
}
void push( Stack* ps, char* str){
if(full(*ps)){
int tempsize = ps->size;
ps->size += 10;
ps->data = realloc(ps->data, ps->size * sizeof(char*));
// char **temp = realloc(ps->data, ps->size*sizeof(char*));
// if(temp == NULL){
// perror("realloc");
// printf("Error! memory not allocated.\n");
// exit(-1);
// }
// ps->data = temp;
printf("Stack capacity has grown from %d elements to %d elements\n", tempsize, ps->size);
}
ps->data[++ps->top] = strdup(str);
}
bool empty( Stack s){
if(s.top == -1)
return TRUE;
return FALSE;
}
char* pop( Stack* ps){
if(empty(*ps))
return NULL;
return ps->data[ps->top--];
}
int main(int argc, char *argv[]){
printf("Assignment 2 Problem 1 by Jasmine Ramirez\n\n");
FILE *input = fopen("data_a2.txt", "r");
if(input == NULL){
perror("fopen");
printf("File %s not found.\n", "data_a2.txt");
exit(EXIT_FAILURE);
}
Stack *s;
s = create(); <---16 bytes in 1 block definitely lost
char str[255];
char *temp = (char*)malloc(sizeof(char)); <---1 bytes in 1 block definitely lost
int i = 0;
while(fscanf(input, "%s\n", str) == 1){
if(strcmp(str, "pop") == 0){
temp = pop(s);
i--;
printf("# of elements after popping: %d\tstring popped: %s\n", i, temp);
free(temp);
}
else{
push(s, str);
i++;
}
}
deleteStack(s);
fclose(input);
return 0;
}
I can't figure out the reason for the 1 byte lost in temp and s is supposed to be taken care of by deleteStack().
At this statement
temp = pop(s);
Pointer to earlier malloced memory is lost so it is leaked.
In deleteStack, you have not freed ps, so that's a leak too, as memory allocated to Stack *s; in create never gets released.
You should free(ps) at the end of deleteStack.
The temp pointer to the single mallocd char is overwritten with the result from pop, so it is leaked. Why do you need to allocate that single char? Just initialize it to NULL, or leave it uninitialized.
In production code, you should always test the value returned from malloc or realloc, and should never assign the result of realloc over your only pointer to the memory you are trying to reallocate. If it reurns NULL, you just leaked it.
Also, in deleteStack, you test for NULL, but then continue to dereference the pointer anyway.
Related
my code is not working but when I change struct stack *sp; to struct stack * sp = (struct stack *) malloc(sizeof(struct stack)); it start working. I am confused in when to allocate memory in heap to struct stack *ptr and when to not. It will be better if u can give me an example when struct stack *ptr can be used and when to use struct stack * sp = (struct stack *) malloc(sizeof(struct stack));
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct stack
{
int size;
int top;
char *arr;
};
int stackTop(struct stack* sp){
return sp->arr[sp->top];
}
int isEmpty(struct stack *ptr)
{
if (ptr->top == -1)
{
return 1;
}
else
{
return 0;
}
}
int isFull(struct stack *ptr)
{
if (ptr->top == ptr->size - 1)
{
return 1;
}
else
{
return 0;
}
}
void push(struct stack* ptr, char val){
if(isFull(ptr)){
printf("Stack Overflow! Cannot push %d to the stack\n", val);
}
else{
ptr->top++;
ptr->arr[ptr->top] = val;
}
}
char pop(struct stack* ptr){
if(isEmpty(ptr)){
printf("Stack Underflow! Cannot pop from the stack\n");
return -1;
}
else{
char val = ptr->arr[ptr->top];
ptr->top--;
return val;
}
}
int precedence(char ch){
if(ch == '*' || ch=='/')
return 3;
else if(ch == '+' || ch=='-')
return 2;
else
return 0;
}
int isOperator(char ch){
if(ch=='+' || ch=='-' ||ch=='*' || ch=='/')
return 1;
else
return 0;
}
char* infixToPostfix(char* infix){
struct stack *sp;
sp->size = 10;
sp->top = -1;
sp->arr = (char *) malloc(sp->size * sizeof(char));
char * postfix = (char *) malloc((strlen(infix)+1) * sizeof(char));
int i=0; // Track infix traversal
int j = 0; // Track postfix addition
while (infix[i]!='\0')
{
if(!isOperator(infix[i])){
postfix[j] = infix[i];
j++;
i++;
}
else{
if(precedence(infix[i])> precedence(stackTop(sp))){
push(sp, infix[i]);
i++;
}
else{
postfix[j] = pop(sp);
j++;
}
}
}
while (!isEmpty(sp))
{
postfix[j] = pop(sp);
j++;
}
postfix[j] = '\0';
return postfix;
}
int main()
{
char * infix = "x-y/z-k*d";
printf("postfix is %s", infixToPostfix(infix));
return 0;
}
Two things to always remember when working with pointers in C:
Memory allocation is your problem. You have to think about the allocation of the memory which a pointer variable points to.
You have to be clear in your mind about the distinction between the pointer versus the data that it points to.
So when you say
struct stack *sp;
that will never work, all by itself. It won't work for a program that's implementing a stack, and it won't work for a program that's implementing any other kind of data structure.
When you write
struct stack *sp;
there is one important thing that you have done, and there is one important thing that you have not done.
The compiler allocates space to store one pointer. This pointer is known as sp. But:
The value of this pointer is indeterminate, which means that it does not point anywhere yet. You can't actually use the pointer variable sp for anything. (Yet.)
Or, in other words, going back to the distinction I mentioned earlier, you have taken care of the pointer but you don't have any data that the pointer points to.
But when you say
sp = malloc(sizeof(struct stack));
(and assuming malloc succeeds), now sp points somewhere: it points to a chunk of properly-allocated memory sufficient to hold one struct stack.
I am new at C programming. I wrote some code for a stack exercise. The question is: one of the result is wrong, but when I debug step by step, the number changed abruptly. Could you help me solve this?
// #name mystack.c
// Created by lilei on 2017/3/10.
//
#include "mystack.h"
#include <malloc.h>
#include <stdio.h>
Stack createStack(){
Stack stack = (Stack)malloc(sizeof(Stack));
stack->top = -1;
return stack;
}
int isFull(Stack s){
if (s->top == MAXSIZE-1){
return 1;
} else{
return 0;
}
}
int push(Stack s, ElementType item){
if(!isFull(s)){
s->top++;
s->data[s->top] = item;
return 1;
} else{
printf("full!");
return 0;
}
}
int isEmpty (Stack s){
if(s->top == -1){
return 1;
} else{
return 0;
}
}
ElementType pop(Stack s){
if(!isEmpty(s)){
ElementType e = s->data[s->top];
s->top--;
return e;
}
}
void myPrintf(Stack s){
int len = s->top;
printf("The data are ");
while(len >= 0){
printf("%d ", s->data[len]);
len--;
}
printf("\n");
}
int main(){
Stack s = createStack();
for(int i = 0; i < 7; i++){
push(s, i*2);
}
myPrintf(s);
printf("isEmpty:%d, isFull:%d\n, pop one:%d", isEmpty(s), isFull(s), pop(s));
}
The result is
I can't see the declaration of Stack because you forgot to put it in th question, but it must be declared as a pointer to a struct e.g.
typedef struct
{
int top;
ElementType data[MAXSIZE];
} *Stack;
// ^- means pointer
So a Stack is a pointer type which means that, when you malloc it, you malloc only 4 or 8 bytes depending on whether you are compiling for 32 or 64 bit. The malloc line should be
Stack stack = malloc(sizeof *stack);
You were not allocating enough space on your stack for the actual stack structure which means that you are writing into bits of the heap you do not own and other things will write into the memory you think you have allocated for your stack.
There is another problem. What does your pop() function return if you try to pop something when the stack is empty? The answer is "could be anything". You either need to abort the program or return some error value.
I tried reading from text file, and then put every word in list node(and print it afterwards in reverse order).
The program works good, but when trying to free the allocated list nodes, the program crash.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
#include <math.h>
typedef struct node{
char* word;
struct node* next;
}; typedef struct node* list;
void freeall(list lst){
list temp = NULL;
while (lst)
{
temp = lst->next;
free(lst);
lst = temp;
}
#if 0
if (lst == NULL){ return; }
freeall(lst->next);
free(lst->word);
free(lst);
#endif // 0
}
void deleteAllNodes(list start)
{
while (start != NULL)
{
list temp = start;
free(temp);
start = start->next;
}
}
list createNode(char* buff){
list newnode = (list)malloc(sizeof(list));
assert(newnode);
newnode->next = NULL;
newnode->word = (char*)calloc(strlen(buff), sizeof(char));
assert(newnode->word);
strcpy(newnode->word, buff);
return newnode;
}
void reverse(const char *str) //you don't need to modify your string
{
if (*str != '\0'){ //if the first character is not '\O'
reverse((str + 1)); // call again the function but with +1 in the pointer addr
printf("%c", *str); // then print the character
}
}
void print_reverse(list lst){
if (lst == NULL) return;
print_reverse(lst->next);
reverse(lst->word);
//free(lst->word);
}
list createList(FILE* ifp){
struct node *loop = NULL;
list curr = NULL;
list lst = NULL;
char *word = NULL;
size_t size = 2;
long fpos = 0;
char format[32];
if (ifp == NULL) // open file
perror("Failed to open file \n");
if ((word = malloc(size)) == NULL) // word memory
perror("Failed to allocate memory");
sprintf(format, "%%%us", (unsigned)size - 1); // format for fscanf
while (fscanf(ifp, format, word) == 1) {
while (strlen(word) >= size - 1) { // is buffer full?
size *= 2; // double buff size
printf("** doubling to %u **\n", (unsigned)size);
if ((word = realloc(word, size)) == NULL)
perror("Failed to reallocate memory");
sprintf(format, "%%%us", (unsigned)size - 1);// new format spec
fseek(ifp, fpos, SEEK_SET); // re-read the line
if (fscanf(ifp, format, word) == 0)
perror("Failed to re-read file");
}
curr = createNode(word);
if (lst == NULL){lst = curr;}
else{
loop = lst;
while (loop->next != NULL) {//loop to last structure
loop = loop->next;//add structure to end
}
loop->next = curr;
}
fpos = ftell(ifp); // mark file pos
}
free(word);
return lst;
}
int main(int argc, char* argv[]){
assert(argc == 2);
FILE *ifp = fopen(argv[1], "r");
assert(ifp);
list lst = NULL;
lst = (list)malloc(sizeof(list));
lst = createList(ifp);
print_reverse(lst);
fclose(ifp);
//freeall(lst);
//deleteAllNodes(lst);
return 1;
}
your delete all nodes has a bug in it. You freed a pointer and tried accessing it immediately. So the program crashes You can try this
void deleteAllNodes(list head)
{
list ptr = head;
while ((ptr = head) != NULL)
{
head = head->next;
free (ptr);
}
}
point the current ptr to the head and point head to next element. Delete the current pointer.
In your deleteAllNodes function you are free-ing a pointer and then accessing it. You could try deleting nodes in reverse order, starting from the last one, for instance with a recursive function.
void deleteAllNodes(list start)
{
if (start != NULL)
{
deleteAllNodes(start->next);
free(start);
}
}
Or you can stick to the iterative forward deletion with something like (untested):
void deleteAllNodes(list start)
{
list previous = NULL;
while (start != NULL)
{
if (previous != NULL)
free(previous);
previous = start;
start = start->next;
}
if (previous != NULL)
free(previous);
}
The problem , as I see it is with
list newnode = (list)malloc(sizeof(list));
your list is a typedef to struct node*, so this statement is essentially
list newnode = (list)malloc(sizeof(struct node*));
which is wrong. You're allocating memory for a pointer to structure variable, whereas, you should be allocating memory equal to the size of the structure variable itself.
Two things to mention here
Please see why not to cast the return value of malloc() and family in C.
Never use a typedef for a pointer type. It's not a "rule", but better to stick to it.
Your allocation statement, at least, shall look like
list = malloc(sizeof*list);
Apart from this, in your main() function,
First, you're allocating memory to lst using malloc() [Same issue with the allocation as above]
Then, you assign another pointer, the return value of createList() to lst.
This way, you're overwriting the allocated mekory through malloc(), creating memory leak. You don't need malloc() there, at all.
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 want to reverse a sentence using stack in c.
eg. how are you => you are how.
i have written the following program
#include<stdio.h>
#include<conio.h>
struct rev
{
char *var;
struct rev *next;
};
struct rev *top=NULL;
struct rev *temp,*test;
main()
{
int start, j = 0;
char *p="Hi, How are you? Hope everything is fine";
char *s;
char *t;
*t = '\0';
s = p;
while(1) {
if(*p == ' '|| *p == '\0') {
printf("Inside if \n");
*(t + j) = '\0';
printf("This is t %s\n",t);
if(top == NULL) {
temp = (struct rev *)malloc(sizeof(struct rev));
temp->next = NULL;
temp->var=t;
top = temp;
} else {
temp = (struct rev *)malloc(sizeof(struct rev));
printf("This is going in stack %s\n", t);
temp->var = t;
temp->next = top;
top = temp;
printf("This is top %s\n", top->var);
}
j = 0;
} else {
*(t+j) = *p;
printf("%c\n", *p);
j++;
}
if(*p == '\0') {
break;
}
//printf("%c",*p);
p++;
}
struct rev *show;
show = top;
while(show != NULL) {
printf("%s\n", show->var);
show = show->next;
}
getch();
}
It is storing correctly but on traverse it is giving only the final element.
i am not be able to figure it out what is the problem.
Here is my output window:-
Read complete line. Tokenize string on whitespace, pushing each word to the stack. Pop the stack while printing.
Useful functions:
fgets
strtok
Complete solution can be done in less than 20 lines (including structure definitions, header files, etc.)
You also have a problem with undefined behavior in your code. You have a pointer p which points to a constant array of characters (all string literals are constant arrays of characters). Then you try to modify that constant array.
You might want something like this instead:
char arr[] = "Some string here";
char *p = arr;
And you have another case of undefined behavior as well: You have the pointer t which is not initialized. You then continue to dereference it. I would say that you are lucky to not get a crash.
You also don't update t in the loop, which you probably should.
First of all your char *t is just a pointer, make it point to malloced memory and then go ahead... I dont understand how the code is even running ... You are doing *(t + j) when t is actually pointing to junk.
On first look You are overwriting t... after parsing a string. i.e you set j = 0 and overwrite previously stored string and your struct rev hold a pointer to this t hence
you are getting you? you? you? as output. instead of having char *var in struct rev point to t .. your char *var point to a malloced memory and do strcpy or strtok
I just did a rough modification of your code and it worked for me on linux + gcc ... Here's the code:
#include<stdio.h>
#include <stdlib.h>
struct rev
{
char *var;
struct rev *next;
};
struct rev *top=NULL;
struct rev *temp,*test;
main()
{
int start, j = 0;
char *p="How are you?";
char *s;
char *t;
t = malloc(1000);
if (t == NULL) {
//OUT OF MEMORY
exit(1);
}
s = p;
while(1) {
if(*p == ' '|| *p == '\0') {
printf("Inside if \n");
*(t + j) = '\0';
printf("This is t %s\n",t);
if(top == NULL) {
temp = (struct rev *)malloc(sizeof(struct rev));
temp->next = NULL;
temp->var = malloc(100);
if (temp->var == NULL) {
//OUT OF MEMORY
exit(1);
}
strcpy(temp->var, t);
top = temp;
} else {
temp = (struct rev *)malloc(sizeof(struct rev));
printf("This is going in stack %s\n", t);
temp->var = malloc(100);
if (temp->var == NULL) {
//OUT OF MEMORY
exit(1);
}
strcpy(temp->var, t);
temp->next = top;
top = temp;
printf("This is top %s\n", top->var);
}
j = 0;
} else {
*(t+j) = *p;
printf("%c\n", *p);
j++;
}
if(*p == '\0') {
break;
}
//printf("%c",*p);
p++;
}
struct rev *show;
show = top;
while(show != NULL) {
printf("%s\n", show->var);
show = show->next;
}
//getch();
}
Here's the output:
H
o
w
Inside if
This is t How
a
r
e
Inside if
This is t are
This is going in stack are
This is top are
y
o
u
?
Inside if
This is t you?
This is going in stack you?
This is top you?
you?
are
How
PS: I dont undertand in which part of the code you are implementing push|pop ... You are using list and telling you want a stack. Stack and List are 2 different data-structures.
You can start by initializing variable t to point to a valid memory address.
It seems that the logic of "show" is written incorrectly-
show = top;
while(show != NULL) {
printf("%s\n", show->var);
show = show->next;
}
pointing show to top and printing "show->next" is incorrect way of popping out from stack.
Here is an example of pop function-
int pop(STACK **head) {
if (empty(*head)) {
fputs("Error: stack underflow\n", stderr);
abort();
} else {
STACK *top = *head;
int value = top->data;
*head = top->next;
free(top);
return value;}}