2 votes

Libérer les tampons locaux lors de la levée d'exceptions en C++

Supposons que j'aie le constructeur suivant dans une classe C++ :

MyClass::MyClass()
{
    char* buffer = malloc(100);
    if (0 != someD3DXCallThatCanFail(..., buffer, ...))
    {
        free(buffer);
        throw MyException(L"some message");
    }
    char* buffer2 = malloc(200);
    if (0 != anotherD3DCallThatCanFail(..., buffer2, ...))
    {
        free(buffer);
        free(buffer2);
        throw MyException(L"another message");
    }
    .. more code here where buffer and buffer2 are still used

    free(buffer);
    free(buffer2);
}

EDIT : Je déteste malloc/free et new/delete, mais malheureusement j'ai besoin d'utiliser des buffers pour charger des textures qui sont ensuite transmises à ID3D10ShaderResourceView, ID3D10Buffer, vertex buffer et autres. Tous ces éléments nécessitent des pointeurs vers un tampon.

Ce que j'essaie de faire, c'est d'utiliser des exceptions au lieu de renvoyer des codes d'erreur. Je souhaite également créer des tampons là où ils sont nécessaires et les libérer dès qu'ils ne sont plus nécessaires.

Cependant, ce qui est moche, c'est qu'en cas d'erreur, que je renvoie des codes d'erreur ou que je lève des exceptions, je ne dois pas oublier de nettoyer le tampon qui a été créé jusqu'à ce moment-là. Si j'ai 10 tampons et 10 points d'erreur possibles, je devrai appeler free() 100 fois (dans chaque cas d'erreur, n'oubliez pas de libérer chaque tampon).

Supposons maintenant que je veuille, ou pire, que mon collègue veuille modifier la logique et, par exemple, ajouter un autre tampon quelque part au milieu. Il devra alors examiner toutes les erreurs qui peuvent se produire dans le reste de la méthode et ajouter free() pour ce tampon à chacun de ces endroits. S'il est pressé, il peut facilement négliger quelques endroits de ce type, et vous avez une fuite de mémoire.

Le code s'en trouve considérablement alourdi.

Enfin, un mot-clé résoudrait ce problème en Java ou en C#. Quel que soit l'endroit du code où l'exception s'est produite, je nettoierais toujours tous ces tampons dans "finally" (entre parenthèses, vous n'en auriez pas besoin avec le garbage collection). En C++, d'après ce que j'ai compris, je devrais peut-être créer une variable membre pour chacun de ces tampons, et dans le destructeur, m'assurer que les tampons sont nettoyés. Cela me semble également assez laid, car une variable membre avec le nom "pBuffer", même privée, n'est qu'un déchet, puisqu'elle n'est utilisée que dans une seule méthode (dans ce cas, le constructeur) et qu'elle sera toujours NULL le reste du temps.

Il doit s'agir d'un problème courant, mais je n'ai pas réussi à trouver de réponse à l'aide de la recherche. Je vous remercie de votre attention.

1voto

smparkes Points 9849

La réponse canonique à cette question sera unique_ptr en C++11. D'ici là, probablement scoped_ptr (http://www.boost.org/doc/libs/1\_47\_0/libs/smart\_ptr/scoped\_ptr.htm) pour les singletons et scoped_array (http://www.boost.org/doc/libs/1\_47\_0/libs/smart\_ptr/scoped\_array.htm) pour les tableaux, tous deux issus de Boost. Vous pouvez également coder l'équivalent vous-même.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X