SIGSEGV具有递归算法

时间:2011-10-03 20:05:42

标签: c++ gdb sigsegv

我实现了一个递归算法,该算法运行大约1730次递归,然后使用神秘的SIGSEGV崩溃。我尝试了我的gdb并获得了以下输出:

Program received signal SIGSEGV, Segmentation fault.
0x000000000040b7da in Town::get_cur_capacity (this=0x61efe0) at ./solver/Darstellung.cpp:54
54      return left_over_capacity;
(gdb) print 0x61efe0
$1 = 6418400
(gdb) print *0x61efe0
Cannot access memory at address 0x61efe0
(gdb) print this
$2 = (const Town * const) 0x61efe0
(gdb) 

如何调试器确实知道它应该是const Town指针但是无法访问内存以给我转储?我非常确定此方法中没有错误,因为它在崩溃前使用了几千次,就像程序中的其他所有功能一样。这是否与操作系统相关的问题有可能吗?我使用的是Linux Ubuntu 64-Bit。

我的简化算法:

bool solveproblem(ptr_to_model) {
        if( way_one(ptr_to_model) )
              return true;

        if(way_two(ptr_to_model) )
              return true;

        if( check_if_solved)
              return true;

        return false;
}

bool way_one(ptr_to_model) {
     for(go_through_current_problem_configuration) {
     if(check_stuff) {
          ptr_to_model->execute_partial_solution(...); //adds another problem configuration to the stack within the model
          if(solveproblem(ptr_to_model))
                  return true;

          ptr_to_model->redo_last_step();
     }
     }
     return false;
}

bool way_two(...) {
   /*basicly the same as way one*/
}

bool check_if_solve(...) {
       if(problem_solved)
              return true;
       else
              return false;
}

该模型与名称类似,它表示算法通过在其堆栈上推送一个新的“层”时所做的所有步骤,这是一个由旧版本构成的修改(快速简化)问题,考虑到部分算法评估的解决方案。希望我把它缩小到可以理解的范围。

2 个答案:

答案 0 :(得分:4)

如果你的递归深度为1700级,那么你就会超越堆栈并破坏一个很容易导致这种崩溃的调用参数,这并不令人难以置信。

如果您使用g ++,请尝试添加-fstack-protector-all以查看它是否有助于您获得更好的诊断。

编辑:另一个指标是,如果你在gdb中的回溯变成圆形或者没有导致任何地方:这是一个强烈的指示,表明堆栈已经损坏。

在回应评论时,没有一种可靠的方法可以确定某些内容是堆栈溢出还是“更正常”的堆损坏。显然,如果可用,valgrind总是一个可靠的内存错误选项。您可以在shell中使用ulimit或以编程方式(我相信)setrlimit来配置堆栈限制。请注意,存在硬上限,并且通常最好将递归更改为更少堆栈滥用而不是增加堆栈大小。

答案 1 :(得分:0)

你在堆栈上传递的参数有多大?在那个深度,如果你为8M堆栈传递大约5k,你可能会溢出。这对堆栈变量来说相当大,但可能。或者,您可能通过写入堆栈中存储的缓冲区的末尾(通常是字符串缓冲区)来粉碎堆栈。你在return崩溃的事实表明这是一种可能性。