세그먼테이션 오류를 일으키는 코드 줄을 결정 하시겠습니까?
코드에서 오류가 발생하여 분할 오류 를 일으키는 위치를 어떻게 알 수 있습니까?
일부 코드를 작성한 후 세그먼테이션 오류가있는 위치를 판별하기 위해 컴파일러 ( gcc
)가 프로그램에서 오류 위치를 표시 할 수 있습니까?
GCC는 그렇게 할 수 없지만 GDB ( 디버거 )는 가능합니다. 다음 -g
과 같이 스위치를 사용하여 프로그래밍 하십시오.
gcc program.c -g
그런 다음 gdb를 사용하십시오.
$ gdb ./a.out
(gdb) run
<segfault happens here>
(gdb) backtrace
<offending code is shown here>
다음 은 GDB를 시작하는 데 유용한 자습서입니다.
또한 Valgrind에 시도해 볼 수 있습니다 : Valgrind를 설치하고 valgrind --leak-check = full을 실행하면 프로그램을 실행하고 모든 segfault에 대한 스택 추적과 유효하지 않은 메모리 읽기 또는 쓰기 및 메모리 누수를 표시합니다 . 정말 유용합니다.
코어 덤프를 사용한 다음 gdb로 검사 할 수도 있습니다. 유용한 정보를 얻으려면 -g
플래그 로 컴파일해야합니다 .
메시지가 나타날 때마다 :
Segmentation fault (core dumped)
코어 파일이 현재 디렉토리에 작성됩니다. 그리고 당신은 명령으로 그것을 확인할 수 있습니다
gdb your_program core_file
파일에는 프로그램 충돌시 메모리 상태가 포함됩니다. 코어 덤프는 소프트웨어 배포 중에 유용 할 수 있습니다.
시스템이 코어 덤프 파일 크기를 0으로 설정하지 않았는지 확인하십시오. 다음을 사용하여 무제한으로 설정할 수 있습니다.
ulimit -c unlimited
조심해! 코어 덤프가 커질 수 있습니다.
세그멘테이션 결함 디버깅에 도움이되는 여러 가지 도구가 있으며, 내가 좋아하는 도구를 목록에 추가하고 싶습니다 : Address Sanitizers (대개 ASAN) .
최신 ¹ 컴파일러에는 편리한 -fsanitize=address
플래그가 제공되어 컴파일 시간과 런타임 오버 헤드가 추가되어 오류 검사가 더 많이 수행됩니다.
에 따르면 문서 이러한 검사는 기본적으로 세그멘테이션 오류를 잡는 포함한다. 여기서 장점은 gdb의 출력과 유사하지만 디버거 내에서 프로그램을 실행하지 않고도 스택 추적을 얻을 수 있다는 것입니다. 예를 들면 :
int main() {
volatile int *ptr = (int*)0;
*ptr = 0;
}
$ gcc -g -fsanitize=address main.c
$ ./a.out
AddressSanitizer:DEADLYSIGNAL
=================================================================
==4848==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x5654348db1a0 bp 0x7ffc05e39240 sp 0x7ffc05e39230 T0)
==4848==The signal is caused by a WRITE memory access.
==4848==Hint: address points to the zero page.
#0 0x5654348db19f in main /tmp/tmp.s3gwjqb8zT/main.c:3
#1 0x7f0e5a052b6a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26b6a)
#2 0x5654348db099 in _start (/tmp/tmp.s3gwjqb8zT/a.out+0x1099)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /tmp/tmp.s3gwjqb8zT/main.c:3 in main
==4848==ABORTING
출력은 gdb가 출력하는 것보다 약간 더 복잡하지만 단점이 있습니다.
스택 추적을 수신하기 위해 문제를 재현 할 필요가 없습니다. 개발 중 플래그를 활성화하는 것만으로 충분합니다.
ASAN은 단순한 세그먼트 오류보다 더 많은 것을 포착합니다. 해당 메모리 영역이 프로세스에 액세스 가능하더라도 많은 범위를 벗어난 액세스가 포착됩니다.
코어 덤프에 대한 Lucas의 답변이 좋습니다. 내 .cshrc에는 다음이 있습니다.
alias core 'ls -lt core; echo where | gdb -core=core -silent; echo "\n"'
'core'를 입력하여 역 추적을 표시합니다. 그리고 날짜 스탬프는 올바른 파일을보고 있는지 확인합니다.
추가 : 스택 손상 버그 가 있으면 코어 덤프에 적용된 역 추적은 종종 쓰레기입니다. 이 경우 gdb 내에서 프로그램을 실행하면 허용되는 답변에 따라 더 나은 결과를 얻을 수 있습니다 (오류가 쉽게 재현 가능하다고 가정). 또한 코어를 동시에 덤프하는 여러 프로세스에주의하십시오. 일부 OS는 PID를 코어 파일 이름에 추가합니다.
'IT' 카테고리의 다른 글
특정 값을 가진 stl 벡터에서 항목을 어떻게 제거합니까? (0) | 2020.06.29 |
---|---|
직렬화 및 역 직렬화 중에 다른 JSON 속성 이름 (0) | 2020.06.29 |
"사용"블록에서 SqlConnection이 반환 또는 예외로 닫혔습니까? (0) | 2020.06.29 |
JSONArray를 반복 할 수 있습니까? (0) | 2020.06.29 |
IntelliJ IDEA의 매개 변수 목록 안에있을 때 메소드 호출 후 세미콜론을 추가하는 방법은 무엇입니까? (0) | 2020.06.29 |