I’m at a complete loss. I feel like there must be some glaring, stupidly easy mistake here, and my eyes are just too tired to see it. I’d really appreciate any help.
When I run testProb2, the program prints “Pushing:” and then on the next line, “Segmentation fault”. I find this really weird, because the next thing after printf(“Pushing:\n”); is another call to printf with just a static argument being passed, nothing dynamic that could be doing weird crazy things in some other method, and yet “1 ” does not get printed.
I put the call to printf for 1 and 2 in there just as a test, because I initially thought that the problem might be in my first for loop, which is commented out right now, but that’s not it. As I said, I believe the problem to be in testProb2.c, but I included stackli.h and stackli.c below it just in case. I’m compiling this with “gcc -ansi stackli.c testProb2.c -o testProb2”.
/* testProb2
*
* Demonstrates a stack implementation that allocates a number of nodes at creation of the stack
* rather than on each call to Push. All methods are O(1) except for GrowFreeList, which is O(n),
* and CreateStack, which is O(n) because it calls GrowFreeList, and possibly Push, which will be
* O(1) when called while there are empty nodes, but O(n) when called if there are not empty nodes.
*/
#include "stackli.h"
#include <stdio.h>
int main(void) {
Stack S;
int i;
S = CreateStack(8);
printf("Pushing:\n");
printf("1 ");
Push(1, S);
printf("2\n");
Push(2, S);
/*
for (i = 0; i < 10; i++) {
printf("%d...", i);
Push(i, S);
}
printf("]\n");
*/
printf("Popping:\n");
while (!IsEmpty(S)) {
printf("%d...", Top(S));
Pop(S);
}
printf("]");
DisposeStack(S);
}
/* stackli.h */
typedef int ElementType;
#ifndef _Stack_h
#define _Stack_h
struct Node;
struct StackRecord;
typedef struct Node *PtrToNode;
typedef struct StackRecord *Stack;
Stack CreateStack( int initialSize );
void GrowFreeList( Stack S );
int IsEmpty( Stack S );
int IsFull( Stack S ) ;
void MakeEmpty( Stack S );
void DisposeStack( Stack S );
void Push( ElementType X, Stack S );
ElementType Top( Stack S );
void Pop( Stack S );
#endif /* _Stack_h */
/* stackli.c */
#include "stackli.h"
#include "fatal.h"
#include <stdlib.h>
struct StackRecord {
PtrToNode ThisStack;
PtrToNode FreeNodes;
int Size;
};
struct Node {
ElementType Element;
PtrToNode Next;
};
/* O(n) instead of O(1) because it calls GrowFreeList which is O(n) */
Stack CreateStack(int initialSize) {
Stack S;
S = malloc( sizeof( struct StackRecord ) );
S->ThisStack = NULL;
S->FreeNodes = NULL;
S->Size = initialSize;
GrowFreeList(S);
return S;
}
/* O(n) function */
void GrowFreeList(Stack S) {
int i;
PtrToNode temp;
for (i = 0; i < S->Size; i++) {
temp = malloc( sizeof( struct Node) );
if (temp == NULL)
FatalError("Out of space!!");
temp->Next = S->FreeNodes;
S->FreeNodes = temp;
}
S->Size = S->Size * 2;
}
The problem is in the last two lines of
Push:When you first call
Push, theThisStackfield is null. When you try to dereference it to access itsNextfield, you are getting a segfault. However, since the top of the stack is inThisStack, notThisStack->next, fixing that problem will get rid of the segfault.You make the same mistake in
Pop, which would cause you to entirely skip the first element. The assignment totempshould be like this:Finally, your
Sizefield will always be wrong. It appears thatGrowFreeListis supposed to double the size of the stack when it is called, but when you call it fromCreateStack, your stack’s real size is 0 although theSizefield is 8 (in your example). The result is that the stack contains 8 free nodes, but itsSizefield is 16. In fact, theSizefield will always be larger than the actual size by the initial size. This doesn’t cause any problems now, since it is only used to determine how many to add, but the fix is simple: reset theSizefield after callingGrowFreeListfromCreateStack: