I have seen the following code,
/* stack.c */
typedef struct Stack *StackPtr;
struct Stack
{
int *mStack;
int mCurSize;
};
StackPtr StackCreate()
{
return (StackPtr) calloc(sizeof(struct Stack), 1);
}
void StackDestroy(StackPtr stack)
{
if (stack)
{
free(stack);
}
}
void StackPush(StackPtr stack, int val)
{
if (! stack)
return;
if (stack->mStack)
{
int newsize = stack->mCurSize + 1;
int *newptr = realloc(stack->mStack, sizeof(struct Stack)*newsize);
if (newptr)
{
stack->mStack = newptr;
stack->mStack[newsize-1] = val;
stack->mCurSize = newsize;
}
}
else
{
stack->mStack = malloc(sizeof(struct Stack));
if (stack->mStack)
{
stack->mStack[0] = val;
stack->mCurSize = 1;
}
}
}
int StackPop(StackPtr stack)
{
if (! StackIsEmpty(stack))
{
return stack->mStack[--stack->mCurSize];
}
return 0;
}
void StackDestroyMyWay(StackPtr stack) // This is my understanding
{
if (stack)
{
if (stack->mStack)
free(stack->mStack);
free(stack);
}
}
int StackIsEmpty(const StackPtr stack)
{
return stack == NULL || stack->mCurSize == 0;
}
/* main.c */
int main(int argc, char *argv[])
{
/* Create a new stack */
StackPtr stack = StackCreate();
int val;
/* push and pop a value to the stack */
printf( "Empty: %d\n", StackIsEmpty(stack));
StackPush(stack, 10);
printf("Empty: %d\n", StackIsEmpty(stack));
val = StackPop(stack);
printf("Popped off: %d\n", val);
printf("Empty: %d\n", StackIsEmpty(stack));
/* clean up the stack */
StackDestroy(stack);
return 0;
}
Question> I assume the original StackDestory is implemented correctly but I don’t understand why we don’t have to free stack->mStack explicitly.
Actually you do have to free
mStacksomewhere or you will leak memory. IfStackDestroydoesn’t do it for you, you’ll have to do it yourself later.When designing an API that allocates and frees stuff think of a few things:
malloc?In your case the client doesn’t even know about the existence of
mStack(technically you could use opaque objects) so, since you allocate it, you should also free it.