C堆栈奇怪的行为

标签 c segmentation-fault stack

我在带有 gcc 4.8.2 的 Ubuntu 14.04 上使用 Hope 函数程序,并执行高度递归函数来查找大量素数。然而,我得到一个段错误:0x000000000040e03f in reach

cell=<error reading variable: Cannot access memory at address 0x7fffff7feff8> at runtime.c:250

访问地址0x7fffff7feff8时发生段错误。

reach 例程所做的是取消标记当前表达式可以到达的堆项(使用垃圾收集标记-清除)。堆栈很深(100000+ 调用),但没有堆栈溢出:

base_memory = 0x7ffff35a4010
top_string = 0x7ffff35a5260
BaseHeap = 0x7ffff35a5260
heap = 0x7ffff603a450
stack = 0x7ffff72da498
TopStack = 0x7ffff7584d60

从base_memory到TopStack的区域是用malloc分配的。

每当我遇到段冲突时,地址总是 0x7fffff7feff8,即使函数非常不同也是如此。

如果你用 google 搜索 0x7fffff7feff8,会发现有相当多的条目与这个地址有段冲突,没有解决问题。

我用代码检查堆地址是否在堆范围内,但它从未失败。

我做了一个gdb

find 0x7ffff35a4010,0x7ffff7584d60,0x7fffff7feff8

什么也没找到。

为什么地址 0x7fffff7feff8 出现在这么多问题中?堆栈机制是否有问题,或者我是否需要针对平台以某种方式更改代码?

最佳答案

这看起来更像是没有地址空间布局随机化的 x86-64 系统上的堆栈溢出。如果堆栈从 0x7fffffff000 开始,就像它们在此类系统上所做的那样,0x7fffff7feff8 可疑接近堆栈开头下方的 8 MB,这是常见的默认线程堆栈大小在 Linux 系统上。

转储 /proc/self/maps 的内容并检查堆栈的开始是否与此匹配(它列在底部),并检查 ulimit -s 查看新进程获得的堆栈大小。如果 /proc/self/maps0x7ffffffff000 列为堆栈地址范围的末尾并且 ulimit -s 打印 8192 ,你所拥有的只是一个堆栈溢出。在这种情况下,快速解决方法是增加新进程(事件 shell 的子进程)的堆栈大小,如下所示:

ulimit -Ss size_in_kilobytes

这将达到 root 可能会或可能不会施加的硬限制。从长远来看,以不太过度递归的方式重写代码可能是个好主意。

此外,如果所有这些都命中要害,您可能应该启用 ASLR(sysctl kernel.randomize_va_sapce=1。如果出现问题,则您的系统迫切需要升级。写 kernel .randomize_va_space = 1/etc/sysctl.conf 以使其永久化。

关于C堆栈奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27751359/

相关文章:

c - 我的 call_system 函数不适用于标记化字符串

linux - 如何在 ucontext* ,linux 中释放堆栈?

c - 我尝试实现 LIFO 和递归来反转 char 数组,但它无法正常工作

c - 使用 C 预处理器递增定义?

c - 无法理解为什么在某些特定测试用例上它显示段错误,而在其他测试用例上它被成功接受

c - 无法将堆栈大小初始化为 0

c - 变量可用于两个函数而无需在 C 中全局化

c++ - 从类函数中显示动态 C 字符串的段错误 11

c - 二叉搜索树 - 迭代检查高度

c++ - 将堆栈实现为链接结构的解码器