문제

그래서 불행히도 특정 오류를 처리하기 위해 abort()를 사용하는 라이브러리 (내가 작성하지 않음)가 있습니다. 응용 프로그램 수준에서 이러한 오류는 복구 할 수 있으므로 사용자가 충돌을 보는 대신 처리하고 싶습니다. 그래서 다음과 같은 코드를 작성하게됩니다. 라코 디스

그다지 우아한 코드는 아닙니다. 이 패턴은 코드의 몇 군데에서 반복되어야하기 때문에, 나는 그것을 약간 단순화하고 재사용 가능한 객체로 감싸고 싶습니다. 내 첫 번째 시도는 신호 처리기의 설정 / 해체를 처리하기 위해 RAII를 사용하는 것입니다 (각 함수가 다른 오류 처리를 필요로하기 때문에 수행해야 함). 그래서 저는 이것을 생각해 냈습니다 : 라코 디스

확실히 function의 본문은 이러한 방식으로 훨씬 더 간단하고 명확하지만 오늘 아침에 생각이 떠 올랐습니다. 작동이 보장 되나요? 내 생각은 다음과 같습니다.

  1. 변동성이 없거나 setjmp / longjmp 호출간에 변경되는 변수는 없습니다.
  2. 일반적으로 longjmpsetjmping과 동일한 스택 프레임의 위치에 returning을 수행하고 있으므로 코드가 함수의 종료 지점에서 컴파일러가 내 보낸 정리 코드를 실행하도록 허용하고 있습니다.
  3. 예상대로 작동하는 것 같습니다.

    하지만 나는 이것이 정의되지 않은 행동 일 가능성이 높다는 느낌을 여전히받습니다. 어떻게 생각하세요?

도움이 되었습니까?

해결책

f가 타사 라이브러리 / 앱에 있다고 가정합니다. 그렇지 않으면 abort를 호출하지 않도록 수정할 수 있기 때문입니다.RAII가 모든 플랫폼 / 컴파일러에서 올바른 결과를 안정적으로 생성하거나 생성하지 않을 수 있다는 점을 감안할 때 몇 가지 옵션이 있습니다.

  • abort와 LD_PRELOAD를 정의하는 작은 공유 객체를 만듭니다.그런 다음 신호 처리기가 아닌 중단시 발생하는 작업을 제어합니다.
  • 하위 프로세스 내에서 f를 실행합니다.그런 다음 반환 코드를 확인하고 실패하면 업데이트 된 입력으로 다시 시도하십시오.
  • RAII를 사용하는 대신 여러 호출 지점에서 원래 유전자 태그 코드를 호출하고 수동으로 설정 / 해체를 명시 적으로 수행하도록합니다.이 경우에도 복사-붙여 넣기가 제거됩니다.

다른 팁

실제로 귀하의 솔루션이 마음에 들었습니다. 테스트 도구에서 유사한 코드를 작성하여 대상 기능이 예상대로 assert()를 수행하는지 확인했습니다.

이 코드가 정의되지 않은 동작을 호출하는 이유를 알 수 없습니다. C 표준은이를 축복하는 것처럼 보입니다. abort()로 인한 핸들러는 핸들러에서 라이브러리 함수를 호출하는 데 대한 제한에서 면제됩니다. (주의 : 이것은 C99의 7.14.1.1 (5)입니다. 슬프게도 C ++ 표준에서 참조하는 버전 인 C90 사본이 없습니다.)

C ++ 03은 추가 제한을 추가합니다. 프로그램의 다른 (대상) 지점으로 제어를 전송하는 throw 된 예외에 의해 자동 객체가 파괴되는 경우, 해당 위치에서 longjmp (jbuf, val)를 호출합니다. 제어를 동일한 (목적지) 지점으로 전달하는 throw 지점에는 정의되지 않은 동작이 있습니다. '변수가 휘발성이거나 setjmp / longjmp 호출 사이에 변경되지 않는다'는 진술에 자동 C ++ 개체 인스턴스화가 포함되어 있다고 가정합니다. (이게 레거시 C 라이브러리라고 생각합니까?)

또는 POSIX 비동기 신호 안전성 (또는 그 결여)이 문제가 아닙니다. abort()는 프로그램 실행과 동시에 SIGABRT를 생성합니다.

가장 큰 우려는 제 3 자 코드의 글로벌 상태를 손상시키는 것입니다. 작성자가 유전자 코드 코드 이전에 상태를 일관성있게 유지하기 위해 노력할 것 같지는 않습니다. 그러나 변수가 변경되지 않는다는 것이 맞다면 문제가되지 않습니다.

표준을 더 잘 이해하는 사람이 나를 틀렸다는 것을 증명할 수 있다면 깨달음을 주셔서 감사합니다.

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