Pregunta

Esta pregunta proporciona más claridad sobre el problema descrito aquí . Hice un poco más de investigación y descubrí que el desenrollado de la pila no está ocurriendo en el siguiente fragmento 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");
}

Compilé este código usando el compilador VC6 SP5 y la salida es "Wrapper constructor :: AddRef !!!" (es decir, el destructor del objeto contenedor que se construyó en la pila no se llama. ¿Es este el comportamiento esperado? ¿O es un error con el compilador VC? ¿Puedo usar algunas banderas del compilador para que el desenrollamiento de la pila ocurra en este caso?

¿Fue útil?

Solución

Si desea utilizar SEH, debe usar la función _set_se_translator y la opción del compilador EHa.

Otros consejos

El estándar de C ++ no da nada con qué trabajar en caso de un comportamiento indefinido. Incluso si la EM lo hace. Eso es una cosa específica de la plataforma, así que ten cuidado. Algunas de estas excepciones de punto flotante se convierten en excepciones de Win32 que puede intentar capturar con _set_se_translator () . El problema es que puedes capturar las excepciones de Win32, pero entonces tu pila no se desenrollará correctamente. Al menos eso no es algo en lo que puedas apostar tu vida. En el que reside la inutilidad del ejercicio.

  

Actualización: la excepción se lanza intencionalmente para comprobar el desenrollado de la pila. La pregunta es por qué el destructor de la clase Wrapper no es llamado. - Naveen

Si este es el caso, no lo hagas. Hay mejores formas de lanzar excepciones que a través de un comportamiento indefinido.

E.g:

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

No se puede eliminar la referencia de un puntero NULL. Está invocando un comportamiento indefinido aquí:

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

Después de esa línea, todas las apuestas están desactivadas y usted podría matarnos a todos;)

p es un puntero a un objeto One . Debe contener la dirección de un objeto One . Lo ha inicializado en 0; no hay ningún objeto en la dirección 0. 0 no es una dirección válida para ningún objeto (esto está garantizado por la norma).

Debido a que la excepción regular de C ++ no maneja este tipo de excepción, tiene que usar SEH que no sabe nada sobre la aplicación y no se desenrolla.

Este es un comportamiento indefinido:

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

En este punto, la aplicación puede bloquearse sin desenrollar la pila.
Si desea probar el desenrollado de la pila, reemplace esto con:

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

¡No debes asignar dinámicamente todos tus objetos, esto es C ++ no Java!

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

    pTest.OnRecvBuffer();

    OutputDebugString("Test");
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top