C堆栈奇怪的行为

C stack odd behavior

我在 Ubuntu 14.04 和 gcc 4.8.2 上使用 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 出现在这么多问题中?堆栈机制是否有问题,或者我是否需要针对平台以某种方式更改代码?

这看起来更像是没有地址 space 布局随机化的 x86-64 系统上的堆栈溢出。如果堆栈从 0x7ffffffff000 开始,就像它们在此类系统上所做的那样,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 使其永久化)。