如何在C程序中删除此分段错误

时间:2011-11-01 06:28:01

标签: c memory memory-management stack-overflow

这里我想解决此代码中的堆栈溢出问题。 在这个代码中,我递归调用函数p 350000次,所以我得到了分段错误 当我删除350000并把300000比它工作正常 这里的分段错误是因为我多次调用函数p的递归调用或者调用递归函数太深。

这不起作用,因为我采用if(i != 350000)。 它的停留时间可能在300000到327480之间。我测试了10次

CODE:

#include <stdio.h>

void p(char *, int);

int main() 
{
    char *a = "HI";
    int b = 10;
    p(a, b);
    printf("\nComplete");
    return 0;

}
void p(char *a, int b) 
{
    static long int i = 0;

    if (i != 350000) 
    {
        printf("\n%ld \t at Hi hello", i);
        i++;
        p(a, b);
    } else 
    {
        return;
    }
}

当我使用valgrind工具检查此代码而不是像这样的valgraind报告错误

==9236== Stack overflow in thread 1: can't grow stack to 0x7fe801ff8
==9236== 
==9236== Process terminating with default action of signal 11 (SIGSEGV)
==9236==  Access not within mapped region at address 0x7FE801FF8
==9236==    at 0x4EA012E: _IO_file_write@@GLIBC_2.2.5 (fileops.c:1276)
==9236==  If you believe this happened as a result of a stack
==9236==  overflow in your program's main thread (unlikely but
==9236==  possible), you can try to increase the size of the
==9236==  main thread stack using the --main-stacksize= flag.
==9236==  The main thread stack size used in this run was 8388608.
==9236== Stack overflow in thread 1: can't grow stack to 0x7fe801ff0
==9236== 
==9236== Process terminating with default action of signal 11 (SIGSEGV)
==9236==  Access not within mapped region at address 0x7FE801FF0
==9236==    at 0x4A2269F: _vgnU_freeres (vg_preloaded.c:58)
==9236==  If you believe this happened as a result of a stack
==9236==  overflow in your program's main thread (unlikely but
==9236==  possible), you can try to increase the size of the
==9236==  main thread stack using the --main-stacksize= flag.
==9236==  The main thread stack size used in this run was 8388608.

请帮助我们,我真的想要这个问题解决方案。我无法从我的代码中删除函数的递归调用。

3 个答案:

答案 0 :(得分:3)

堆栈是无限的资源。递归非常适合于相对快速地减少搜索空间的算法(排序数组的二进制切换,二进制或多路树遍历等)。

如果你发现自己的算法要求递归到三百五十次,你真的应该重新考虑使用递归解决方案。

例如:

def addUnsigned (a, b):
    if a == 0:
        return b
    return addUnsigned (a-1, b+1)

不适合递归。

如果确实无法删除递归,那么您需要执行valgrind建议的操作,更改堆栈大小。例如,我系统上的链接编辑器ld有一个--stack选项,允许您指定保留的(以及可选的,已提交的)堆栈大小。

答案 1 :(得分:1)

使用该特定示例,如果您将编译器的优化级别调高到足够高,则应执行尾调用消除,这将解决堆栈溢出问题(例如,gcc 4.4.5在-O2处执行此操作以上)。

答案 2 :(得分:0)

如果您仍想以编程方式控制它,可以在线程中调用函数并设置线程的堆栈大小(并等待线程完成)。