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/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
使其永久化)。
我在 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/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
使其永久化)。