Question

Cette question permet de mieux comprendre le problème décrit ici . J'ai fait des recherches plus poussées et j'ai constaté que le code suivant n'était pas en train de dérouler la pile:

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

J'ai compilé ce code à l'aide du compilateur VC6 SP5 et le résultat est "Wrapper constructor :: AddRef !!!". (c’est-à-dire que le destructeur de l’enveloppe qui a été construit sur la pile n’est pas appelé. Est-ce le comportement attendu? ou est-ce un bogue avec le compilateur VC? Puis-je utiliser des indicateurs de compilateur pour que le déroulement de la pile se produise dans ce cas?

Était-ce utile?

La solution

Si vous souhaitez utiliser SEH, vous devez utiliser la fonction _set_se_translator et l'option du compilateur / EHa.

Autres conseils

La norme C ++ ne fournit aucune information à utiliser en cas de comportement indéfini. Même si MS le fait. C'est une chose spécifique à la plate-forme - alors méfiez-vous. Certaines de ces exceptions en virgule flottante sont transformées en exceptions Win32 que vous pouvez essayer d'intercepter avec _set_se_translator () . Le problème est que vous pouvez intercepter des exceptions Win32, mais votre pile ne sera alors pas déroulée correctement. Au moins, ce n'est pas une chose sur laquelle vous pouvez parier votre vie. En quoi consiste la futilité de l'exercice.

  

Mise à jour: une exception est générée intentionnellement pour vérifier le déroulement de la pile. La question est de savoir pourquoi le destructeur de la classe Wrapper n'est pas appelé. & # 8211; Naveen

Si tel est le cas, ne le faites pas. Il existe de meilleurs moyens de générer des exceptions que via le comportement non défini.

E.g:

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

Vous ne pouvez pas déréférencer un pointeur NULL. Vous invoquez le comportement non défini ici:

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

Après cette ligne, tous les paris sont ouverts et vous pourriez nous tuer tous;)

p est un pointeur sur un objet One . Il devrait contenir l'adresse d'un objet One . Vous l'avez initialisé à 0 - il n'y a pas d'objet à l'adresse 0. 0 n'est une adresse valide pour aucun objet (ceci est garanti par la norme).

Etant donné que l'exception régulière C ++ ne gère pas ce type d'exception, vous devez utiliser SEH, qui ne connaît rien de l'application et ne se décompresse pas.

Ce comportement n'est pas défini:

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

À ce stade, l'application est libre de planter sans décharger la pile.
Si vous souhaitez tester le déroulement de la pile, remplacez-le par:

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

Vous ne devez pas allouer dynamiquement tous vos objets. C ++ et non Java!

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

    pTest.OnRecvBuffer();

    OutputDebugString("Test");
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top