Pergunta

Esta questão fornece mais clareza sobre o problema descrito aqui . Eu fiz mais algumas investigações e descobriu que a pilha desenrolar não está acontecendo no seguinte trecho de código:

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");
}

Eu compilei este código usando o compilador VC6 SP5 ea saída é "Wrapper construtor :: AddRef !!!" (Ou seja, o destruidor de objeto wrapper que foi construído na pilha não é chamado. Esse é o comportamento esperado? Ou é um bug com o compilador VC? Posso usar algumas opções de compilação para que o desenrolamento pilha acontece nesse caso?

Foi útil?

Solução

Se você quiser usar SEH, você deve usar _set_se_translator função e / opção de compilador EHa.

Outras dicas

padrão A C ++ não dá nada para o trabalho com em caso de comportamento indefinido. Mesmo MS faz. Isso é uma coisa plataforma específica - por isso tome cuidado. Alguns desses flutuantes exceções de ponto estão voltados para exceções Win32 que você pode tentar pegar com _set_se_translator(). O problema é que você pode capturar exceções Win32, mas, em seguida, sua pilha não será desenrolado corretamente. Pelo menos isso não é algo que você pode apostar sua vida. Onde reside a futilidade do exercício.

Update: A exceção é lançada intencionalmente para verificar o desenrolar pilha. A questão é por destruidor da classe Wrapper não está sendo chamado. - Naveen

Se este for o caso - não fazê-lo. Há maneiras melhores para lançar exceções do que via um comportamento indefinido.

por exemplo:

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

Você não pode excluir a referência um ponteiro NULL. Você está invocando um comportamento indefinido aqui:

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

Depois que a linha todas as apostas estão fora e você pode ter nos matado todos;)

p é um ponteiro para um objeto One. Ele deve conter o endereço de um objeto One. Você inicializado para 0 - não há nenhum objeto no endereço 0. 0 não é um endereço válido para qualquer objeto (isto é guranteed pelo padrão)

.

Porque exceção regulares C ++ não lidar com este tipo de exceção, você tem que usar SEH que não sabe nada sobre o aplicativo e não relaxar.

Este é um comportamento indefinido:

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

Neste ponto, o aplicativo é gratuito para falhar sem desenrolar a pilha.
Se você quiser testar a pilha desenrolar substituir este com:

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

Você não deve alocar dinamicamente todos os seus objcts este é C ++ não Java!

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

    pTest.OnRecvBuffer();

    OutputDebugString("Test");
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top