만들기 실수는 더 이상 오류가 없습니다

오늘의 주제는 : 특정 세그먼트 널 포인터 오류 (분할 오류)에 방문 할 것인가?

아래의 코드를보고 :
TEST.C를

#include <stdio.h>

int main()
{
    int *p = NULL;

    *p = 1;

    return 0;
}

너무 많은 코드를 작성하는 리눅스 내부에서, 그것은 때문에 방문 널 포인터로, 위의 코드 세그먼트 오류가 명확해야한다.

#gcc test.c -o test
#./test
Segmentation fault
#

현상과 우리는 같은 생각합니다. 리눅스, 방문 또는 필드 가이드 경우 널 포인터에서 실수 메모리의 보호를위한 운영 체제입니다 (분할 오류)가있을 것이다. 실수가 발생하면, 시스템이 신호 (11) (SIGSEGV)를 전송한다,이 신호가 수신되면, 프로그램은 끊었다. 의 검증하자 :

circle.c

#include <stdio.h>

int main()
{
    while (1);

    return 0;
}

간단한 무한 루프 프로그램 및 실행은 다음 죽일 후 SIGSEGV 신호를 송신하는 단말기, 제 질의 프로세스 PID를 열고 :

그림 삽입 설명 여기
그런 다음 프로그램의 실행 결과를 보면 :

그림 삽입 설명 여기분명히하지 같은 현상이 발생하고 프로그램 세그먼트 오류 현상.

그것은 잘 리눅스 내부에 알려져, 신호의 처리 과정은 무시 캡처하는 방법은 세 가지 기본 동작이 있습니다. 정상적인 상황에서는, 당신은 그와 같은 CTRL + C와 같은 기본 동작은 프로세스 다이를하게됩니다에는 아무 것도 할 필요가 없습니다.

그러나 다음과 같은 과정 후, CTRL + C는 죽지 않고, 또한 물건을 인쇄하려면 :

signal.c

#include <stdio.h>
#include <signal.h>

void handler(int sig)
{
    printf("receive signal %d\n", sig);
}

int main()
{
    signal(SIGINT, handler);

    while (1);

    return 0;
}

컴파일 및 실행, 다음 Ctrl + C 타격 유지 :

그림 삽입 설명 여기
그 이유는 프로세스 SIGINT 신호 번호 2 우리는 촬상이다 간단하다. 이 또한 알 수있는 ps 명령 (주 열이 적발)

그림 삽입 설명 여기
물론, 우리는 그것을 무시하도록 선택할 수 있습니다 :

#include <stdio.h>
#include <signal.h>

int main()
{
    signal(SIGINT, SIG_IGN);

    while (1);

    return 0;
}

아무 소용이, CTRL + C를 누르면 아무리 :

그림 삽입 설명 여기
우리는 여전히 PS 볼 수 있습니다 (주이 열 무시) :

그림 삽입 설명 여기유사한 신호 SIGKILL 소수 이외에 SIGSTOP이 캡처 외부 무시할 수 많은 신호에서 다른 쪽이 SIGSEGV 세그먼트 오류 포함 물론 우리 플레이하는데 사용될 수있다 (제 11 보이는 Niubi 으르렁 ) 신호.

당신은, 당신은 결코를 죽일 때 프로세스를 종료에 해당하는 CTRL + C 및 다른 신호를 사용할 때 반복적 것을 강조했지만,이 신호에 대한 응답으로 A와 A를 신호를 전송 때 해당 동작은 프로세스 종료입니다. 그것은 과정이 아니다 그래서 당신은 죽일,하지만 당신은 죽을 신호, "통지"A 대상 프로세스를 보냅니다. 그래서 당신은 리눅스 킬을 이해하기 위해 인간 세계를 죽일 수 없습니다. 리눅스의 유사한 논리 : 당신에게 맞아요 프로세스 A : "당신은 지옥에 갈"(이 다이에 신호를 보낼 수 있습니다), 보류중인 신호이를보고 난 후에는 즉시 죽은 숨막히는, 무슨 말도 안되는 말을하지 않습니다! 그래서, 당신은 단지의 응답 동작을 변경, 당신은 죽음을 선택할 수 있습니다.

여기에 문제가 간단하다, 우리는 setjmp는 사용하고 세그먼트 오류를 ​​구현하는 longjmp가 계속 :

#include <stdio.h>
#include <signal.h>
#include <setjmp.h>

jmp_buf env;

void handler(int sig)
{
    longjmp(env, 1);         //跳转到上一次保存的现场
}

int main()
{
    int ret = setjmp(env);   //保存执行现场,返回0
    if (0 == ret)
    {   
        signal(SIGSEGV, handler);

        printf("制造段错误...\n");
        int *p = NULL;
        *p = 1;
    }   
    else
    {   
        printf("段错误后!\n");
    }

    return 0;
}

이 setjmp 함수의 원리는 다음과 같습니다

이 실행 사이트를 저장이 함수를 호출하고, 0을 반환; longjmp를 호출 한 후, 사이트, 다시 setjmp는 수익을 저장하는 복원, 이번에 반환하는 longjmp ()는 두 번째 매개 변수하다 setjmp는. 다음 차트 봐 :

그림 삽입 설명 여기
우리가 약간의 코드를 변경 한 경우, 줄을 삭제 :

#include <stdio.h>
#include <signal.h>
#include <setjmp.h>

jmp_buf env;

void handler(int sig)
{
    longjmp(env, 1);         //跳转到上一次保存的现场
}

int main()
{
    int ret = setjmp(env);   //保存执行现场,返回0
    if (0 == ret)
    {   
        //signal(SIGSEGV, handler);

        printf("制造段错误...\n");
        int *p = NULL;
        *p = 1;
    }   
    else
    {   
        printf("段错误后!\n");
    }

    return 0;
}

현상은 우리에게 친숙한 :

그림 삽입 설명 여기
오류 신호 세그먼트에만 발급 운영 시스템 메모리를 보호하는 것입니다, 이해하지 못했지만, 프로세스가 너무 라인에 SIGSEGV를 무시하는 실수를 방지하기 위해, 끊기 처리하는 신호의 기본을 받는다. 관심이 메모리에 액세스 할 수없는 액세스하지 않는 경우 물론,이 절대적으로 최후의 수단이며, 수정 실수로이 방법을 사용하면, 더 중요한 여전히 쓰기 코드 메모리 사용량 단순히 침묵이다.

더 많은 기사, 비디오, 임베디드 학습 자료, 마이크로 채널 공공 우려 번호는 "지능형 하드웨어의 장점을 배웠습니다."

그림 삽입 설명 여기

게시 12 개 원래 기사 · 원의 찬양 (24) · 전망 2436

추천

출처blog.csdn.net/xiaopengX6/article/details/104596666