程序在释放时接收SIGTRAP [英] Program receives SIGTRAP while freeing

查看:129
本文介绍了程序在释放时接收SIGTRAP的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好,



我试图在C中创建一个类似堆栈的实现,(基本上以堆栈的方式将整数存储到缓冲区),但是我的实现遇到了一些问题 - 特别是在Windows系统上。

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.

// 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;
}





但是,当我调用此程序时,它会在free处生成一个SIGTRAP(由GDB报告)异常stack->内容)我很确定这是一个堆栈损坏的情况,我的程序正在运行的地方不应该......

关于我如何进行的任何想法解决这个问题?

来自gcc -S的汇编输出(如果有人要求的话):



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):

....
; 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
...



......从我的角度来看,这看起来还不错。

编辑:感谢OriginalGriff,我使用了他的a中发布的方法nswer,它完美无瑕!这是他的方法(在代码中)如果有人在将来关心这个:)


...which looks pretty okay from my point of view.
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 :)

#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? :)

推荐答案

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
保留
.cfi_restore 5
.cfi_def_cfa < span class =code-digit> 4 , 4
ret
.cfi_endproc
...
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 ...



......从我的角度来看,这看起来还不错。

编辑:感谢OriginalGriff,我使用了他的答案中公布的方法,它完美无瑕!这是他的方法(在代码中)如果有人在将来关心这个:)


...which looks pretty okay from my point of view.
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 :)

#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? :)


你到底在做什么?

你每次弹出一个项目时似乎都在重新分配堆栈空间 - 大概是每当你也可以添加一些东西。



这真的非常低效:即使你将堆栈作为链表实现,你也会获得更好的性能! :笑:



我怎么做(假设你这样做,这样你就可以拥有一个无限的堆栈):



Stack有三个项目:内容指针,内容大小计数器和栈顶索引。最初,你没有分配空间,并将TOS和SOC都设置为零。

当你推,你检查堆栈是否已满:TOS是否与SOC相同?如果是,则需要分配新堆栈。如果SOC为零,则为16个项目分配空间。如果不是,分配两倍,复制,并释放旧堆栈。

添加新项目,并增加TOS

当你POP,检查TOS:如果它为零,那就是堆栈下溢错误。否则,将TOS减少1并返回新TOS的值。



您可能还想提供一个空功能,释放所有内存,并使用TOS和SOC再次归零。
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.


这篇关于程序在释放时接收SIGTRAP的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆