문제

버스 오류와 분할 오류의 차이점은 무엇입니까?프로그램이 처음으로 세그먼트 오류를 ​​발생시키고 중지하고 두 번째로 버스 오류를 발생시키고 종료될 수 있습니까?

도움이 되었습니까?

해결책

내가 사용한 대부분의 아키텍처에서 차이점은 다음과 같습니다.

  • SEGV는 의도하지 않은 메모리에 액세스 할 때 발생합니다 (예 : 주소 공간 외부).
  • SIGBU는 CPU의 정렬 문제로 인해 발생합니다 (예 : 4의 배수가 아닌 주소에서 오래 읽으려고합니다).

다른 팁

SIGBUS 당신이 경우에도 제기됩니다 mmap() 공간 부족과 같은 오류 조건뿐만 아니라 파일 끝을 지나 확장되는 매핑된 버퍼의 일부에 액세스하려고 시도합니다.다음을 사용하여 신호 처리기를 등록하면 sigaction() 그리고 당신은 설정 SA_SIGINFO, 프로그램에서 오류가 발생한 메모리 주소를 검사하고 메모리 매핑된 파일 오류만 처리하도록 하는 것이 가능할 수 있습니다.

예를 들어, 프로그램이 하드웨어 버스가 지원하지 않는 작업을 수행하려고 할 때 버스 오류가 발생할 수 있습니다. 에 sparc, 예를 들어, 홀수 주소에서 멀티 바이트 값 (예 : int, 32 비트)을 읽으려고하면 버스 오류가 발생했습니다.

세분화 결함은 예를 들어 세분화 규칙을 위반하는 액세스를 수행 할 때 발생합니다. 즉, 소유하지 않은 메모리를 읽거나 쓰려고합니다.

나는 당신이 SIGSEGV 그리고 SIGBUS POSIX에 의해 정의 된 신호.

SIGSEGV 프로그램이 잘못된 주소를 참조 할 때 발생합니다. SIGBUS 구현 정의 하드웨어 결함입니다. 이 두 신호의 기본 조치는 프로그램을 종료하는 것입니다.

프로그램은 이러한 신호를 포착하고 심지어 무시할 수도 있습니다.

귀하의 질문을 (아마도 잘못) "Sigsegv 또는 Sigbus를 간헐적으로 받고 있습니다. 왜 일관성이 없습니까?"를 의미하는 것으로 해석합니다. C 또는 C ++ 표준에 의해 포인터로 Dodgy를 수행하는 것은 보장되지 않는다는 점에 주목할 가치가 있습니다. segfault; 그것은 단지 "정의되지 않은 행동"일 뿐이며, 교수로서 한 번 말한 것은 악어가 바닥판에서 나오고 당신을 먹을 수 있음을 의미합니다.

그래서 당신의 상황은 당신이 두 개의 버그를 가지고 있다는 것입니다. 때때로 SIGSEGV를 일으키고 두 번째 (Segfault가 발생하지 않고 프로그램이 여전히 실행중인 경우)는 Sigbus를 유발합니다.

디버거를 사용하여 악어를 찾는 것이 좋습니다.

이것은 DUP 일 것입니다 버스 오류는 무엇입니까?, 그렇지 않은 경우

프로그램이 SEG 결함을주고 처음으로 멈추고 두 번째로 버스 오류와 종료 될 수 있습니까?

질문의 일부. 여기에있는 정보로 직접 답변 할 수 있어야합니다.


광기 : 반복해서 같은 일을하고 다른 결과를 기대합니다.
-Albert 아인슈타인


물론, 문자 그대로 질문을받습니다 ...

#include <signal.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
int main() {
    srand(time(NULL));
    if (rand() % 2)
        kill(getpid(), SIGBUS);
    else
        kill(getpid(), SIGSEGV);
    return 0;
}

Tada, 한 번에 세분화 오류로 종료하고 다른 달리기에서 버스 오류로 종료 할 수있는 프로그램입니다.

프로그램이 SEG 결함을주고 처음으로 멈추고 두 번째로 버스 오류와 종료 될 수 있습니까?

그렇습니다. 하나와 동일한 버그의 경우에도 : 여기에는 배열의 경계 외부의 인덱스에 의해 SIGSEGV (Segmentation Fault) 및 버스 오류 (SIGBUS)를 모두 생성 할 수있는 MACOS의 심각하지만 단순한 예가 있습니다. 위에서 언급 한 정렬되지 않은 액세스는 MACOS의 문제가 아닙니다. (이 예제는 디버거 내부에서 실행되면 SIGBUS를 유발하지 않습니다. lldb 나의 경우에는!)

bus_segv.c :

#include <stdlib.h>

char array[10];

int main(int argc, char *argv[]) {
    return array[atol(argv[1])];
}

이 예제는 명령 줄에서 정수를 가져와 배열의 인덱스 역할을합니다. 어떤 인덱스 값 (배열 외부에서도)이 신호를 유발하지 않습니다. (표준 세그먼트/섹션 크기에 따라 주어진 모든 값은 Clang-902.0.39.1을 사용하여 높은 시에라 MacOS 10.13.5, i5-4288U CPU @ 2.60GHz에서 이진을 생성했습니다.)

77791 이상 이하 이하 -4128 이하의 인덱스는 세분화 오류 (SIGSEGV)를 유발합니다. 24544는 버스 오류 (SIGBUS)를 유발합니다. 여기에서 전체지도 :

$ ./bus_segv -4129
Segmentation fault: 11
$ ./bus_segv -4128
...
$ ./bus_segv 24543
$ ./bus_segv 24544
Bus error: 10
...
$ ./bus_segv 28639
Bus error: 10
$ ./bus_segv 28640
...
$ ./bus_segv 45023
$ ./bus_segv 45024
Bus error: 10
...
$ ./bus_segv 53215
Bus error: 10
$ ./bus_segv 53216
...
$ ./bus_segv 69599
$ ./bus_segv 69600
Bus error: 10
...
$ ./bus_segv 73695
Bus error: 10
$ ./bus_segv 73696
...
$ ./bus_segv 77791
$ ./bus_segv 77792
Segmentation fault: 11

분해 된 코드를 보면 버스 오류가있는 범위의 경계가 인덱스가 나타나는 것만 큼 이상하지 않다는 것을 알 수 있습니다.

$ otool -tv bus_segv

bus_segv:
(__TEXT,__text) section
_main:
0000000100000f60    pushq   %rbp
0000000100000f61    movq    %rsp, %rbp
0000000100000f64    subq    $0x10, %rsp
0000000100000f68    movl    $0x0, -0x4(%rbp)
0000000100000f6f    movl    %edi, -0x8(%rbp)
0000000100000f72    movq    %rsi, -0x10(%rbp)
0000000100000f76    movq    -0x10(%rbp), %rsi
0000000100000f7a    movq    0x8(%rsi), %rdi
0000000100000f7e    callq   0x100000f94 ## symbol stub for: _atol
0000000100000f83    leaq    0x96(%rip), %rsi
0000000100000f8a    movsbl  (%rsi,%rax), %eax
0000000100000f8e    addq    $0x10, %rsp
0000000100000f92    popq    %rbp    
0000000100000f93    retq    

에 의해 leaq 0x96(%rip), %rsi, RSI는 배열 시작 주소의 (비교적 결정된) 주소가됩니다.

rsi = 0x100000f8a + 0x96 = 0x100001020
rsi - 4128 = 0x100000000 (below segmentation fault)
rsi + 24544 = 0x100007000 (here and above bus error)
rsi + 28640 = 0x100008000 (below bus error)
rsi + 45024 = 0x10000c000 (here and above bus error)
rsi + 53216 = 0x10000e000 (below bus error)
rsi + 69600 = 0x100012000 (here and above bus error)
rsi + 73696 = 0x100013000 (below bus error)
rsi + 77792 = 0x100014000 (here and above segmentation fault)

lldb 아마도 페이지 제한이 다른 프로세스를 설정할 수 있습니다. 디버그 세션에서 버스 오류를 재현 할 수 없었습니다. 따라서 디버거는 버스 오류가 발생한 바지에 대한 해결 방법 일 수 있습니다.

안드레아스

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top