2015-01-03 3 views
3

우분투 14.04에서 gcc 4.8.2와 함께 Hope 함수 프로그램을 사용하고 많은 수의 소수를 찾기 위해 매우 재귀 함수를 사용하고 있습니다. 그러나, 나는 세그먼트 오류를 ​​얻을 : 0x000000000040e03f에 도달C stack odd behavior

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 

TopStack에 base_memory에서 영역 malloc에 ​​할당되었다.

세그먼트 위반이 발생할 때마다 주소는 매우 다른 기능을 사용하더라도 항상 0x7fffff7feff8입니다.

Google의 주소가 0x7fffff7feff8 인 경우이 주소로 세그먼트 위반이있는 항목이 몇 개 있으며 문제가 해결되지 않았습니다.

힙 주소가 힙 범위에 있는지 확인하는 코드를 넣었지만 결코 실패하지 않았습니다.

나는

find 0x7ffff35a4010,0x7ffff7584d60,0x7fffff7feff8 

아무것도 발견 된 GDB를했다.

주소가 0x7fffff7feff8인데 왜 많은 문제가 있습니까? 스택 메커니즘에 문제가 있습니까? 아니면 플랫폼에서 어떤 식 으로든 코드를 변경해야합니까?

+3

코드 위치> (BTW, 더 많은 정보를 얻으려면 큰 소수를 찾는 것이 좋습니다!) –

+0

코드가 복잡하다고 생각합니다. 오류 주소 0x7fffff7feff8은 Google에서 꽤 많이 나타나는 것처럼 보이고 세그먼트 위반은 gdb를 사용하는 것이 의미가 없으므로 패턴이나 일반적인 오류의 일종이 있습니다. – DougT

+0

'valgrind'에서 프로그램을 실행하면 문제가있는 곳을 알 수 있습니다. 당신이 이미 그것을했다면,이 코멘트를 건너 뛰십시오 :) – Diego

답변

4

주소 공간 레이아웃 임의 화없이 x86-64 시스템에서 스택 오버플로처럼 보입니다. 스택이 0x7ffffffff000에서 시작하는 경우 해당 시스템에서와 마찬가지로 0x7fffff7feff8은 스택 시작 부분보다 8MB 가까이 가깝습니다. 이는 Linux 시스템에서 일반적인 기본 스레드 스택 크기입니다.

/proc/self/maps의 내용을 덤프하고 스택의 시작 부분이 일치하는지 (하단에 나열되어 있는지) 확인하고 ulimit -s을 확인하여 새 프로세스가 얻는 스택 크기를 확인합니다. /proc/self/maps이 스택 주소 범위의 끝에 0x7ffffffff000을 나열하고 ulimit -s8192 인 경우 단순히 스택 오버플로가됩니다. 이 경우, 빠른 수정과 같이 새로운 프로세스 (액티브 쉘의 서브 프로세스)의 스택 크기를 증가하는 것입니다 : 이것은 또는 부과하지 않을 수 있습니다 엄격한 제한 root까지 작동합니다

ulimit -Ss size_in_kilobytes 

. 장기적으로 볼 때 코드를 덜 지나치게 재귀 적으로 다시 작성하는 것이 좋습니다. 이 모든 집에 안타

또한, 당신은 아마 ASLR 활성화해야합니다 (sysctl kernel.randomize_va_sapce=1을. 그 불평 경우 시스템 업그레이드 절실히 필요하다.이 영구적으로 /etc/sysctl.conf-kernel.randomize_va_space = 1 쓰기).

+0

귀하의 분석이 정확합니다. /etc/sysctl.conf에 kernel.randomize_va_space = 1을 쓰는 것이 가장 효과적 이었지만 ulimit -s를 변경하는 것도 도움이되었습니다. 함수형 프로그래밍에서 대부분의 것은 재귀를 통해 수행됩니다. 꼬리를 재귀 적으로 만들려고 할 수 있으므로 스택 크기가 그렇게 커지지는 않습니다. 나는 지금 행복한 야영 자다. – DougT

+0

수정 : ASLR을 사용하여 차이는 없었지만 ulimit을 변경하면 큰 차이가 발생했습니다. - – DougT

+0

네, 맞습니다. ASLR은 크기가 아닌 스택의 위치 만 변경해야하며 코드는 다른 시작점에서와 동일한 방식으로 확장됩니다. ASLR을 사용하면'/ proc/self/maps'에 다른 스택 범위가 표시되어야하며 스택 오버 플로우는 다른 주소에서 발생해야합니다. – Wintermute