C stack odd behavior

Refresh

November 2018

Views

396 time

3

I am using the Hope functional program on Ubuntu 14.04 with gcc 4.8.2, and doing a highly recursive function to find a large number of prime numbers. However, I get a segmentation fault: 0x000000000040e03f in reach

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

The segmentation fault occurs when accessing address 0x7fffff7feff8.

What the reach routine is doing is unmarking heap items that can be reached by the current expression (using a garbage collection mark-sweep). The stack is very deep (100000+ calls), but there is not a stack overflow:

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

The area from base_memory to TopStack was allocated with malloc.

Whenever I get a segment violation, the address is always 0x7fffff7feff8, even with very different functions.

If you google 0x7fffff7feff8 there are quite a few entries with segment violations with this address, with no solution to the problem.

I put code into check that the heap address was in the heap range, but it never failed.

I did a gdb

find 0x7ffff35a4010,0x7ffff7584d60,0x7fffff7feff8

and nothing was found.

Why does the address 0x7fffff7feff8 show up in so many problems? Is there something amiss with the stack mechanism, or do I need to change the code in some way for the platform?

1 answers

4

Это скорее похоже на переполнение стека на x86-64 в системе без адрес компоновки пространства рандомизации. Если стек начинается 0x7ffffffff000, как они делают на таких системах, 0x7fffff7feff8подозрительно близко к 8 МБ ниже начала стека, который является общим по умолчанию размер стека потока в системах Linux.

Дамп содержимого /proc/self/mapsи проверьте , если начало стеки соответствует этому (она указана в нижней части ), и проверьте , ulimit -sчтобы увидеть размер стека новых процессов получения. Если /proc/self/mapsсписки 0x7ffffffff000как конец диапазона адресов стеки и ulimit -sгравюры 8192, что у вас есть просто переполнение стека. В этом случае, быстрое решение было бы увеличить размер стека новых процессов (подпроцессов активной оболочки) , как так:

ulimit -Ss size_in_kilobytes

Это будет работать на жесткий лимит rootможет или не может навязать. В долгосрочной перспективе, вероятно , было бы хорошей идеей , чтобы переписать код менее чрезмерно рекурсивным способом.

Кроме того , если все это попадает домой, вы , вероятно , следует включить ASLR ( sysctl kernel.randomize_va_sapce=1. Если это жалуется, ваша система остро нуждается в обновлении. Написать kernel.randomize_va_space = 1в /etc/sysctl.confсделать его постоянным).