programing

setjmp/longjmp 및 지역 변수

css3 2023. 10. 17. 20:27

setjmp/longjmp 및 지역 변수

제 질문은 지역 변수에 대한 setjmp/longjmp의 행동을 목표로 합니다.

예제 코드:

jmp_buf env;


void abc()
{
  int error;

  ... 
  if(error)
    longjmp(env);
}


void xyz() {
  int v1;           // non-volatile; changed between setjmp and longjmp
  int v2;           // non-volatile; not changed between setjmp and longjmp
  volatile int v3;  // volatile;     changed between setjmp and longjmp
  volatile int v4;  // volatile;     not changed between setjmp and longjmp 

  ...

  if(setjmp(env)) {
    // error handling
    ...
    return;
  }

  v1++; // change v1
  v3++; // change v3

  abc();
}


int main(...) {
  xyz();
}

setjmp/longjmp의 문서에는 다음과 같이 나와 있습니다.

"접근 가능한 모든 개체는 longjmp()가 호출된 시간을 기준으로 값을 갖습니다.다만 휘발성 한정형이 아닌 해당 setjmp () 호출을 포함하는 함수에 로컬이고 setjmp () 호출과 longjmp () 호출 간에 변경되는 자동 저장 기간의 객체 값은 불확정됩니다."

다음과 같은 두 가지 가능한 해석이 있습니다.

해석1:

로컬 변수가 복원되지만 둘 다 해당되는 변수는 제외됩니다.

  • 비휘발성의
  • 변경되었다.

해석2:

로컬 변수는 다음을 제외하고 복원됩니다.

  • 휘발성이 없는 것과
  • 변경된 것들

longjmp 후의 해석 1에 따르면 v1만 정의되지 않습니다. v2, v3, v4가 정의됩니다.longjmp 후의 해석 2에 따르면 v4만 정의되고 v1, v2, v3는 정의되지 않습니다.

어느 쪽이 맞습니까?

BTW: 모든 컴파일러에 유효한 일반적인 ("휴대용") 답변이 필요합니다. 즉, 특정 컴파일러 하나로 시도해 보는 것은 도움이 되지 않습니다.

setjmp/longjmp는 처음 통과할 때 레지스터(스택, 코드 포인터 등 포함)를 저장하고 점프할 때 복원하는 방식으로 구현됩니다.

'휘발성'이 아닌 자동(일명 "로컬", 스택 할당) 변수는 스택이 아닌 레지스터에 저장될 수 있습니다.

이러한 상황에서 longjmp는 이러한 레지스터 변수를 setjmp()가 처음 호출된 시점의 값으로 복원합니다.

또한, 특히 영리한 컴파일러는 다른 변수의 상태로부터 추론할 수 있는 변수를 회피하여 요구에 따라 계산할 수 있습니다.

그러나 변수가 자동이지만 레지스터가 할당되지 않은 경우 setjmp와 longjmp 사이의 코드에 의해 변경될 수 있습니다.

Volatile은 컴파일러에게 해당 변수를 레지스터에 저장하지 말라고 명시적으로 말하고 있습니다.

따라서 변수가 휘발성이라고 명시적으로 말하지 않는 한 setjmp/longjmp 사이의 변수를 변경했다면 값은 컴파일러의 선택에 따라 달라지므로 의존해야 할 것은 없습니다('불확정').

해석 1이 맞습니다.해석 2가 의도된 경우 원본 텍스트는 "그리고" 대신 "또는 변경된"을 사용했을 것입니다.

언급URL : https://stackoverflow.com/questions/1393443/setjmp-longjmp-and-local-variables