세그멘테이션 결함 처리
나는 분할 오류나 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
'programing' 카테고리의 다른 글
| 한 줄 if-condition 할당 (0) | 2023.06.29 |
|---|---|
| git 커밋 서명 실패: 비밀 키를 사용할 수 없습니다. (0) | 2023.06.29 |
| 공통 테이블 식, 세미콜론이 필요한 이유는 무엇입니까? (0) | 2023.06.29 |
| 다른 컨테이너의 도커 몽고 이미지 '연결 거부됨' (0) | 2023.06.29 |
| Git: fatal: Pathspec이 하위 모듈에 있습니다. (0) | 2023.06.29 |