mélange de gestion des exceptions c ++ et SEH (Windows)

J’ai une fonction dans laquelle j’appelle getaddrinfo() pour obtenir un sockaddr* dont la mémoire cible est allouée par le système. Comme beaucoup de personnes le savent peut-être, vous devez appeler freeaddrinfo() pour libérer la mémoire allouée par getaddrinfo ().

Maintenant, dans ma fonction, il y a quelques endroits où je peux lancer une exception, car certaines fonctions ont échoué. Ma première solution consistait à incorporer freeaddrinfo() à chaque if-block. Mais cela m’était moche, parce que j’aurais dû l’appeler de toute façon avant le retour de mon poste, alors j’ai eu l’essai final de SEH …

Mais le problème que j’ai rencontré est qu’il n’est pas permis de coder les instructions throw dans le bloc __try

Ensuite, j’ai lu sur le msdn et essayé d’échanger les instructions throw dans la fonction d’aide appelée depuis le bloc __try … et le tour est joué, le compilateur ne le gémit plus …

Pourquoi donc? Et est-ce sécuritaire? Cela n’a pas de sens pour moi: /

Code:

 void function() { //... addrinfo* pFinal; __try { getaddrinfo(..., &pFinal); //if(DoSomething1() == FAILED) // throw(exception); //error C2712: Cannot use __try in functions that require object unwinding //but this works Helper(); //... } __finally { freeaddrinfo(); } } void Helper() { throw(Exception); } 

MODIFIER:

essayé ce qui suit et cela fonctionne avec le lancement d’un entier, mais ne fonctionne pas lorsque j’utilise une classe comme exception:

 class X { public: X(){}; ~X(){}; }; void Helper() { throw(X()); } void base() { __try { std::cout << "entering __try\n"; Helper(); std::cout << "leaving __try\n"; } __finally { std::cout << "in __finally\n"; } }; int _tmain(int argc, _TCHAR* argv[]) { try { base(); } catch(int& X) { std::cout << "caught a X" << std::endl; } std::cin.get(); return 0; } 

Pourquoi? : /

Vous pouvez envelopper addrinfo dans une classe qui appelle getaddrinfo dans le constructeur et freeaddrinfo dans son destructeur.

Ainsi, il sera toujours libéré, qu’une exception soit levée ou non.

Vous ne pouvez pas mélanger les deux types d’exception. Sous les couvertures, les exceptions C ++ utilisent SEH et votre gestionnaire d’exceptions SEH risque de gâcher la logique de propagation des exceptions. En conséquence, le compilateur C ++ ne vous permettra pas de les mélanger.

PS: La gestion des exceptions structurées est presque toujours une très mauvaise idée. En interne, Microsoft a interdit l’utilisation de SEH, sauf dans des circonstances très limitées. Tout composant qui utilise la gestion structurée des exceptions est automatiquement soumis à des révisions intensives du code (nous disposons d’outils qui parsingnt le code à la recherche de son utilisation afin de s’assurer qu’aucun cas n’est omis).

Le problème avec SEH est qu’il est extrêmement facile d’introduire accidentellement des vulnérabilités de sécurité lorsqu’on utilise SEH.

 catch(int& X) { std::cout << "caught a X" << std::endl; } 

Cela n'attrape pas un X , mais un int& . Comme il n'y a pas de bloc catch correspondant, l'exception est non capturée, le déroulage de stack ne se produit pas et les gestionnaires __finally ne s'exécutent pas.

Vous pouvez mettre catch (...) dans le point d'entrée de votre thread (qui est main() pour le thread principal) afin de vous assurer que le déroulement de la stack se produit, bien que certaines exceptions soient irrécupérables, ce n'est jamais le cas d'une exception C ++.