스택 풀기 란 무엇입니까? 란 무엇입니까?

스택 풀기 란 무엇입니까? 검색했지만 깨달은 답변을 찾을 수 없습니다!



답변

스택 해제는 일반적으로 예외 처리와 관련하여 설명됩니다. 예를 들면 다음과 같습니다.

void func( int x )
{
    char* pleak = new char[1024]; // might be lost => memory leak
    std::string s( "hello world" ); // will be properly destructed

    if ( x ) throw std::runtime_error( "boom" );

    delete [] pleak; // will only get here if x == 0. if x!=0, throw exception
}

int main()
{
    try
    {
        func( 10 );
    }
    catch ( const std::exception& e )
    {
        return 1;
    }

    return 0;
}

여기 pleak에서 예외가 발생하면 할당 된 메모리 가 손실되고 할당 된 메모리 는 어떤 경우에도 소멸자에 s의해 올바르게 해제됩니다 std::string. 범위가 종료되면 스택에 할당 된 객체는 “풀림”상태입니다 (여기서는 범위가 함수 func입니다). 이는 컴파일러가 자동 (스택) 변수의 소멸자에 대한 호출을 삽입하여 수행됩니다.

이제 이것은 C ++에서 메모리, 데이터베이스 연결, 열린 파일 디스크립터 등과 같은 리소스를 관리하는 데 도움 되는 RAII 라는 기술 ( 리소스 획득이 초기화 임)로 이어지는 매우 강력한 개념 입니다.

이제 우리는 예외 안전 보장 을 제공 할 수 있습니다 .


답변

이 모든 것은 C ++과 관련이 있습니다.

정의 : 힙 메모리에 객체를 할당하는 대신 스택에 객체를 정적으로 만들고 함수 호출을 수행하면 “스택”됩니다.

범위 ( {및로 구분 된 })가 종료 return XXX;되면 (를 사용 하여 범위의 끝에 도달하거나 예외를 throw하여) 해당 범위 내의 모든 항목이 삭제됩니다 (소멸자가 모든 것을 호출 함). 로컬 객체를 파괴하고 소멸자를 호출하는 이러한 프로세스를 스택 해제라고합니다.

스택 해제와 관련하여 다음과 같은 문제가 있습니다.

  1. (아무것도 동적으로 유출 될 로컬 객체에 의해 관리되고 소멸자에서 정리되지 않도록 할당) 메모리 누수를 방지 – RAII는 참조 라고 니콜라이에 의해, 그리고 부스트 :: scoped_ptr를 설명서 또는 사용의 예 부스트 :: 뮤텍스를 :: scoped_lock .

  2. 프로그램 일관성 : C ++ 사양에 따르면 기존 예외를 처리하기 전에 예외를 throw해서는 안됩니다. 이것은 스택 해제 프로세스가 예외를 발생시키지 않아야 함을 의미합니다 (소멸자를 던지지 않도록 보장 된 코드 만 사용하고 try {및 으로 소멸자의 모든 것을 둘러싸십시오 } catch(...) {}).

스택 해제 중에 소멸자가 예외를 throw하면 정의되지 않은 동작 이 발생하여 프로그램이 예기치 않게 종료되거나 (가장 일반적인 동작) 유니버스가 종료됩니다 (이론적으로 가능하지만 실제로는 아직 관찰되지 않음).


답변

일반적으로 스택 “언 와인드 (unwind)”는 함수 호출의 끝과 그에 따른 스택의 팝핑과 거의 동의어입니다.

그러나 특히 C ++의 경우 스택 해제는 C ++이 코드 블록이 시작된 이후 할당 된 객체에 대해 소멸자를 호출하는 방법과 관련이 있습니다. 블록 내에서 생성 된 개체는 할당 순서와 반대로 할당이 해제됩니다.


답변

스택 해제는 주로 C ++ 개념으로, 범위가 종료 될 때 (일반적으로 또는 예외를 통해) 스택 할당 된 객체가 소멸되는 방식을 처리합니다.

이 코드 조각이 있다고 가정 해보십시오.

void hw() {
    string hello("Hello, ");
    string world("world!\n");
    cout << hello << world;
} // at this point, "world" is destroyed, followed by "hello"


답변

글을 아직 읽었는지 모르겠지만 , 콜 스택에 관한 Wikipedia의 기사 에는 적절한 설명이 있습니다.

풀기 :

호출 된 함수에서 리턴하면 스택에서 맨 위 프레임이 튀어 나와 리턴 값이 남습니다. 프로그램의 다른 곳에서 실행을 재개하기 위해 스택에서 하나 이상의 프레임을 팝하는보다 일반적인 동작을 스택 해제 라고합니다. 하며 예외 처리에 사용되는 것과 같이 로컬이 아닌 제어 구조를 사용할 때 수행해야합니다. 이 경우 함수의 스택 프레임에는 예외 핸들러를 지정하는 하나 이상의 항목이 포함됩니다. 예외가 발생하면 처리 된 예외 유형을 처리 (캐치) 할 수있는 핸들러가 발견 될 때까지 스택이 풀립니다.

일부 언어에는 일반적인 풀기를 필요로하는 다른 제어 구조가 있습니다. 파스칼을 사용하면 전역 goto 문이 중첩 된 함수에서 이전에 호출 된 외부 함수로 제어를 전송할 수 있습니다. 이 작업을 수행하려면 스택을 풀어야하는데, 외부 컨텍스트 내에서 대상 명령문으로 제어를 전송하기 위해 적절한 컨텍스트를 복원하는 데 필요한만큼의 스택 프레임을 제거해야합니다. 마찬가지로 C에는 로컬이 아닌 gotos로 작동하는 setjmp 및 longjmp 함수가 있습니다. Common Lisp을 사용하면 unwind-protect 특수 연산자를 사용하여 스택이 풀릴 때 발생하는 상황을 제어 할 수 있습니다.

연속을 적용 할 때 스택은 (논리적으로) 풀린 다음 연속 스택으로 다시 감습니다. 이것이 연속을 구현하는 유일한 방법은 아닙니다. 예를 들어, 여러 개의 명시 적 스택을 사용하여 연속 적용은 단순히 스택을 활성화하고 전달할 값을 감을 수 있습니다. Scheme 프로그래밍 언어는 연속이 호출 될 때 제어 스택의 “풀기”또는 “되감기”의 지정된 지점에서 임의의 썽크가 실행될 수 있도록합니다.

검사 [편집]


답변

이해하는 데 도움이되는 블로그 게시물을 읽었습니다.

스택 풀기 란 무엇입니까?

재귀 함수를 지원하는 모든 언어 (예 : Fortran 77 및 Brainf * ck를 제외한 거의 모든 언어)에서 언어 런타임은 현재 실행중인 함수의 스택을 유지합니다. 스택 해제는 해당 스택을 검사하고 수정하는 방법입니다.

왜 그렇게 하시겠습니까?

답은 명백해 보일 수 있지만 풀리는 것이 유용하거나 필요한 몇 가지 관련되어 있지만 미묘하게 다른 상황이 있습니다.

  1. 런타임 제어 흐름 메커니즘으로 (C ++ 예외, C longjmp () 등)
  2. 디버거에서 사용자에게 스택을 표시합니다.
  3. 프로파일 러에서 스택 샘플을 가져옵니다.
  4. 프로그램 자체에서 (예 : 스택을 표시하는 충돌 처리기에서)

이들은 미묘하게 다른 요구 사항이 있습니다. 이들 중 일부는 성능이 중요하고 일부는 그렇지 않습니다. 일부는 외부 프레임에서 레지스터를 재구성하는 기능이 필요하지만 일부는 그렇지 않습니다. 그러나 우리는 잠시 후에 모든 것을 시작할 것입니다.

여기 에서 전체 게시물을 찾을 수 있습니다 .


답변

모든 사람들이 C ++의 예외 처리에 대해 이야기했습니다. 그러나 스택 풀림에 대한 또 다른 의미가 있다고 생각하며 디버깅과 관련이 있습니다. 디버거는 현재 프레임 이전의 프레임으로 이동해야 할 때마다 스택 해제를 수행해야합니다. 그러나 이것은 현재 프레임으로 돌아올 때 되감기해야하는 일종의 가상 풀기입니다. 이에 대한 예는 gdb의 up / down / bt 명령 일 수 있습니다.