我在带有 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/maps
将 0x7ffffffff000
列为堆栈地址范围的末尾并且 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/