Click here to Skip to main content
15,887,676 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hello,

I've tried to create a stack-like implementation in C, (basically storing integers to a buffer in a "stackish" way), however I've been experiencing some problems with my implementation --- specifically on Windows systems.
C#
// In Header file
.....
typedef struct __stack {
        int* content;
        int no;
} stack_t;
// In Source file
.....
int PopFromStack(stack_t* stack)
{
        int a = stack->content[stack->no];
        stack->no--;
        int* new_content_stk = (int*)malloc(stack->no * sizeof(int));
        for (int i = 0; i < stack->no - 1; i++)
        {
                new_content_stk[i] = stack->content[i];
        }
        free(stack->content);
        stack->content = new_content_stk;
        return a;
}


However, when I call this procedure it generates a SIGTRAP (reported by GDB) exception exactly at "free(stack->content)" I'm pretty sure this is a case of stack corruption and my program is running where it isn't supposed to...
Any ideas about how I go on to solve this problem?
Assembler output from "gcc -S" (in case anyone asks for it):
ASM
....
; Specifically the section that deals with free() in the above code
L18:
	movl	8(%ebp), %eax
	movl	4(%eax), %eax
	subl	$1, %eax
	cmpl	-12(%ebp), %eax
	jg	L19
	movl	8(%ebp), %eax
	movl	(%eax), %eax
	movl	%eax, (%esp)
	call	_free
	movl	8(%ebp), %eax
	movl	-20(%ebp), %edx
	movl	%edx, (%eax)
	movl	-16(%ebp), %eax
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
...

...which looks pretty okay from my point of view.
EDIT: Thanks to OriginalGriff, I've used the method posted in his answer, and it works flawlessly! Here's the method by him (in code) if anyone cares about this in future :)
C#
#define DEFAULT_STACK_SIZE 16*sizeof(int)
#define STACK_UFLOW_ERR -1
typedef struct __stack {
    int* content;
    int top_of_stack;
    int stack_count;
}
......
stack_t* CreateStack(void)
{
    stack_t* new_stack = (stack_t*)malloc(sizeof(stack_t)); // Allocate stack structure
    // Set stack and other vars to null
    new_stack->content = NULL;
    new_stack->top_of_stack = 0;
    new_stack->stack_count = 0;
    return new_stack;
}
int PushtoStack(stack_t* stack, int object)
{
    // Check if we are going to overflow
    if (stack->stack_count == stack->top_of_stack){
        // Check if there exists a buffer
        if (stack->stack_count == 0){
            // Allocate, null out and set.
            int* new_buf = (int*)malloc(DEFAULT_STACK_SIZE); // could use calloc here, but not sure abt performance
            memset((void*)new_buf, 0, DEFAULT_STACK_SIZE);
            stack->stack_count = 16;
            stack->content = new_buf;
        }
        else {
            // Allocate it double the size to make sure we don't run out too soon
            int* new_buf = (int*)malloc(stack->stack_count * 2 * sizeof(int));
            memset((void*)new_buf, 0, stack->stack_count * 2 * sizeof(int));
            // Copy the old buffer
            memcpy(new_buf, stack->content, stack->stack_count * sizeof(int));
            // Free it, set the new buffer, and the new size
            free(stack->content);
            stack->content = new_buf;
            stack->stack_count = stack->stack_count * 2;
        }
    }
    // finally push it.
    stack->content[stack->top_of_stack] = object;
    stack->top_of_stack++;
    return 0;
}
int PopFromStack(stack_t* stack)
{
    // if top of stack is 0, return an underflow error else decrement top of stack
    if (stack->top_of_stack == 0){
        return STACK_UFLOW_ERR;
    }
    else {
        stack->top_of_stack--;
        return stack->top_of_stack;
    }
}

Any more improvements/suggestions? :)
Posted
Updated 1-Dec-14 22:31pm
v3

1 solution

What the heck are you doing that for?
You appear to be reallocating the stack space each time you pop an item off it - and presumably whenever you add something to it as well.

That really is spectacularly inefficient: you would get considerably better performance even if you implemented your stack as a linked list! :laugh:

How I would do it (assuming you are doing it this way so that you can have a "limitless" stack):

Stack has three items: a content pointer, a size-of-content counter, and a top-of-stack index. Initially, you allocate no space, and set both TOS and SOC to zero.
When you PUSH, you check if the stack is full : is the TOS the same as the SOC? If it is, you need to allocate a new stack. If SOC is zero, allocate space for 16 items. If it isn't, allocate twice as many as it did have, copy over, and free the old stack.
Add the new item, and increment TOS
When you POP, check the TOS: if it's zero, that's a stack underflow error. Otherwise, reduce TOS by one and return the value at the new TOS.

You might want to also provide an "empty" function which releases all memory, and stes TOS and SOC to zero again.
 
Share this answer
 
Comments
sid2x 2-Dec-14 4:32am    
Thanks! I've used your method as described and it's fixed now..
OriginalGriff 2-Dec-14 4:50am    
You're welcome!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900