programing

세그멘테이션 결함 처리

jooyons 2023. 6. 29. 20:04
반응형

세그멘테이션 결함 처리

나는 분할 오류나 ctrl-c를 잡는 데 사용하는 응용 프로그램이 있습니다.아래 코드를 사용하여 분할 오류를 발견할 수 있지만 핸들러가 계속해서 호출됩니다.어떻게 하면 막을 수 있을까요?참고로, 저는 제 애플리케이션을 종료하고 싶지 않습니다.손상된 버퍼를 모두 제거할 수 있습니다.

가능합니까?

void SignalInit(void )
{

struct sigaction sigIntHandler;

sigIntHandler.sa_handler = mysighandler;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGINT, &sigIntHandler, NULL);
sigaction(SIGSEGV, &sigIntHandler, NULL);

}

핸들러는 이렇게 합니다.

void mysighandler()
{
MyfreeBuffers(); /*related to my applciation*/
}

여기서 세그멘테이션 오류 신호의 경우 핸들러가 여러 번 호출되며 MyfreeBuffers()는 이미 확보된 메모리를 확보하기 위한 오류를 제공합니다.나는 단지 한 번만 무료로 하고 싶지만 여전히 애플리케이션을 종료하고 싶지 않습니다.

제발 도와주세요.

다과같은작대기작업본한에와 같은 .SIGSEGV프로세스를 종료하는 것이지만 프로세스에 대한 처리기를 설치하면 기본 동작을 재정의하는 처리기가 호출됩니다.그러나 문제는 핸들러가 완료된 후 오류 발생 명령이 재시도될 수 있으며, 첫 번째 오류를 해결하기 위한 조치를 취하지 않은 경우 재시도된 명령이 다시 오류가 발생하여 계속 진행된다는 것입니다.

그래서 먼저 그 결과를 초래한 지시를 발견합니다.SIGSEGV그리고 그것을 고치려고 노력하세요 (당신은 다음과 같은 것을 부를 수 있습니다.backtrace()핸들러에서 무엇이 잘못되었는지 직접 확인합니다.)

또한 POSIX 표준에는 다음과 같이 나와 있습니다.

kill(), [RTS] sigqueue() 또는 raise()에 의해 생성되지 않은 [XSI] SIGBUS, SIGFPE, SIGIL 또는 SIGSEGV 신호에 대한 신호 캡처 기능에서 정상적으로 반환된 후 프로세스의 동작이 정의되지 않습니다.

그래서, 가장 이상적인 것은 처음부터 여러분의 단층을 고치는 것입니다.segfault에 대한 처리기는 기본 오류 조건을 무시하기 위한 것이 아닙니다.

그래서 가장 좋은 제안은- 잡지 말고, 핵을 버리게 놔두는 것입니다.코어를 분석합니다.잘못된 메모리 참조를 수정하면 됩니다!

저는 "SIGSEGV를 잡지 마세요"라는 말에 전혀 동의하지 않습니다.

예상치 못한 상황에 대처하기에 꽤 좋은 연습입니다.그리고 그것은 다음과 관련된 신호 메커니즘으로 NULL 포인터(malloc 장애에 의해 주어진)에 대처하는 것이 훨씬 더 깨끗합니다.setjmp/longjmp오류 상태 관리를 코드 전체에 배포하는 것보다 더 효율적입니다.

, 'sigaction'에서 '에는 'sigaction'을 사용합니다.SEGV라고 말하는 것을 잊어서는 안됩니다.SA_NODEFERsa_flags할 수 .SEGV한 번만 핸들러를 트리거합니다.

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

static void do_segv()
{
  int *segv;

  segv = 0; /* malloc(a_huge_amount); */

  *segv = 1;
}

sigjmp_buf point;

static void handler(int sig, siginfo_t *dont_care, void *dont_care_either)
{
   longjmp(point, 1);
}

int main()
{
  struct sigaction sa;

  memset(&sa, 0, sizeof(sigaction));
  sigemptyset(&sa.sa_mask);

  sa.sa_flags     = SA_NODEFER;
  sa.sa_sigaction = handler;

  sigaction(SIGSEGV, &sa, NULL); /* ignore whether it works or not */ 

  if (setjmp(point) == 0)
   do_segv();

  else
    fprintf(stderr, "rather unexpected error\n");

  return 0;
}

에 약에만.SIGSEGV다시 불이 붙습니다. 분명한 결론은 에 대한 전화입니다.MyfreeBuffers();근본적인 문제를 해결하지 못했습니다(그리고 그 함수가 실제로만 하는 경우).free()할당된 메모리가 있는데, 왜 그렇게 생각하는지 모르겠습니다.

략대, 대략.SIGSEGV액세스할 수 없는 메모리 주소에 액세스하려고 시도하면 실행됩니다.프로그램을 에 액세스할 수 있도록 하거나, 실행 를 용프로종액주메해세소다합응수변으로 .longjmp().

그 다음에 계속하려고 하면 안 됩니다.SIG_SEGV이는 기본적으로 애플리케이션 환경이 어떤 방식으로든 손상되었음을 의미합니다.방금 null 포인터를 참조하지 않거나 버그로 인해 프로그램 스택이나 힙 또는 포인터 변수가 손상되었을 수 있습니다.안전한 유일한 방법은 프로그램을 종료하는 것입니다.

통제 C를 다루는 것은 완벽하게 합법적입니다.많은 응용 프로그램들이 이를 수행하지만 신호 처리기에서 정확히 무엇을 하는지 주의해야 합니다.재진입하지 않은 함수는 호출할 수 없습니다.그래서 만약 당신이MyFreeBuffers()는 stddlib stdlib을 합니다.free()기능, 당신은 아마 망했을 것입니다. 중인 동안 가 control-C를 malloc()또는free()따라서 힙 할당을 추적하기 위해 사용하는 데이터 구조를 절반쯤 조작하는 과정에서 호출하면 힙이 거의 손상될 것입니다.malloc()또는free()신호 처리기에서.

신호 처리기에서 안전하게 할 수 있는 유일한 방법은 신호를 잡았다는 것을 알리는 플래그를 설정하는 것입니다.그런 다음 프로그램에서 주기적으로 플래그를 폴링하여 작업을 수행해야 하는지 여부를 결정할 수 있습니다.

상태 변수를 설정할 수 있고 설정되지 않은 경우에만 메모리를 사용할 수 있습니다.신호 처리기는 매번 호출될 것이고, 당신은 그 AFAIK를 제어할 수 없습니다.

SIG_SEGV에서 복구하는 경우를 확인할 수 있습니다. 루프에서 이벤트를 처리하고 이러한 이벤트 중 하나가 Segmentation Violation(분할 위반)을 발생시킨 경우 이 이벤트를 건너뛰기만 하면 됩니다. 나머지 이벤트를 계속 처리하십시오.내 눈에는 SIG_SEGV가 NullPointer와 유사합니다.Java에서는 예외입니다.예, 이 두 가지 중 하나가 지나면 상태가 일관되지 않고 알 수 없지만 경우에 따라 상황을 처리하고 계속하려고 합니다.예를 들어, Algo 거래에서는 주문의 실행을 일시 중지하고 거래자가 전체 시스템을 파괴하거나 다른 모든 주문을 망치지 않고 수동으로 인수할 수 있습니다.

적어도 리눅스에서는 -fnon-call-exceptions 옵션을 사용하는 트릭을 사용하는 것이 해결책이 될 수 있는 것 같습니다.신호를 일반적인 C++ 예외로 변환하고 일반적인 방법으로 처리할 수 있는 기능을 제공합니다.Linux3/gcc46: "-fnon-call-exceptions"를 보십시오. 어떤 신호가 트랩 명령입니까?예를들면.

언급URL : https://stackoverflow.com/questions/10202941/segmentation-fault-handling

반응형