문제

이 질문은 설명 된 문제에 대한 명확성을 제공합니다 여기. 나는 더 많은 조사를했고 스택 풀기가 다음 코드에서 일어나지 않는다는 것을 발견했습니다.

class One
{
public:
    int x ;
};

class Wrapper
{
public:
    Wrapper(CString csText):mcsText(csText)
    {
        CString csTempText;
        csTempText.Format("Wrapper constructor :: %s\n", mcsText);
        OutputDebugString(csTempText);
    }

    ~Wrapper()
    {
        CString csTempText;
        csTempText.Format("Wrapper destructor :: %s\n", mcsText);
        OutputDebugString(csTempText);
    }
    CString mcsText;
};
class Test
{
    public:

    void notifyError()
    {
        try
        {
            int x = 10; 
        }
        catch(...)  {}
    }

    void OnRecvBuffer()
    {
        try
        {
            Wrapper a("AddRef");    
            One* p = NULL;
            p->x = 10;
        }
        catch(...)
        {
            notifyError();
        }   
    }   
};



int main() 
{
    Test* pTest = new Test;

    pTest->OnRecvBuffer();

    OutputDebugString("Test");
}

VC6 SP5 컴파일러를 사용 하여이 코드를 컴파일했으며 출력은 "래퍼 생성자 :: addRef !!!"입니다. (즉, 스택에 구성된 래퍼 객체의 파괴자는 호출되지 않습니다. 이것이 예상되는 동작입니까?

도움이 되었습니까?

해결책

SEH를 사용하려면 _SET_SE_TRANSLATOR 기능 및 /EHA 컴파일러 옵션을 사용해야합니다.

다른 팁

C ++ 표준은 정의되지 않은 동작의 경우 작업 할 것이 없습니다. MS가 그렇게하더라도. 그것은 플랫폼 구체적인 것입니다. 따라서 조심하십시오. 그러한 부동 소수점 예외는 당신이 잡을 수있는 Win32 예외로 바뀝니다. _set_se_translator(). 문제는 Win32 예외를 포착 할 수 있지만 스택은 제대로 풀리지 않습니다. 적어도 그것은 당신이 당신의 삶에 걸릴 수있는 것이 아닙니다. 여기서 운동의 무익함이 있습니다.

업데이트 : 스택 풀기를 확인하기 위해 의도적으로 예외가 발생합니다. 문제는 래퍼 클래스의 파괴자가 호출되지 않는 이유입니다. - Naveen

이것이 사실이라면 -하지 마십시오. 정의되지 않은 행동보다 예외를 던지는 더 좋은 방법이 있습니다.

예 :

void OnRecvBuffer()
{
    try
    {
        Wrapper a("AddRef");    
        throw 42; // this'll throw an exception without invoking UB
    }
    catch(...)
    {
        notifyError();
    }
}

널 포인터를 피할 수는 없습니다. 당신은 여기에서 정의되지 않은 행동을 호출하고 있습니다.

One* p = NULL;
p->x = 10;

그 라인 후 모든 베팅은 꺼져 있습니다 ~할 수 있었다 우리 모두를 죽였습니다;)

p A에 대한 포인터입니다 One 물체. an의 주소를 포함해야합니다 One 물체. 당신은 그것을 0으로 초기화했습니다 - 주소 0에는 객체가 없습니다. 0은 어떤 객체에 대한 유효한 주소가 아닙니다 (이것은 표준에 따라 guranteed).

C ++ 일반 예외는 이러한 종류의 예외를 처리하지 않기 때문에 앱에 대해 알지 못하고 긴장을 풀지 않는 SEH를 사용해야합니다.

이것은 정의되지 않은 행동입니다.

One* p = NULL;
p->x = 10;

이 시점에서 응용 프로그램은 스택을 풀지 않고 자유롭게 충돌 할 수 있습니다.
스택 풀기를 테스트하려면 다음과 같이 바꾸십시오.

 throw 42; // Life the Universe and Everything thrown away

모든 OBJCT를 동적으로 할당해서는 안됩니다. 이것은 Java가 아닌 C ++입니다!

int main() 
{
    Test    pTest;   // Note the lack of new!

    pTest.OnRecvBuffer();

    OutputDebugString("Test");
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top