2 votes

@try-@finally pour garantir l'élimination des fuites de mémoire lors du traitement d'objets non suivis par ARC

Supposons que nous allouions manuellement la mémoire avec malloc()/calloc() ou l'allocation de certains objets qui ne sont pas suivis par ARC (comme CGContextRef ). Ensuite, on fait des trucs. Et finalement, on a besoin de libérer cette mémoire.

Exemple :

void *buf = NULL;     // malloc() allocated object example
CGContextRef context; // Non-manageable by ARC object example

@try {
    buf = malloc(bufSize);
    context = CGBitmapContextCreate(buf, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaNone);

    // Some exception-prone stuff is going here
}
@catch (NSException *e) {
    // ...
}
@finally {
    CGContextRelease(context);
    free(buf);
}

Est-ce que le fait de placer une allocation/désallocation de mémoire dans un @try-@finally est l'approche la meilleure/la plus appropriée/la plus recommandée pour garantir que la mémoire sera libérée au cas où une exception serait levée dans la section "do stuff" ?

Dans le cas contraire, pourriez-vous suggérer une meilleure technique et expliquer pourquoi elle est préférable ?

4voto

Rob Napier Points 92148

Est-ce que le fait de placer une allocation/désallocation de mémoire dans un @try-@finally est l'approche la meilleure/la plus appropriée/la plus recommandée pour garantir que la mémoire sera libérée au cas où une exception serait levée dans la section "do stuff" ?

No.

On doit toujours s'attendre à ce qu'une exception ObjC conduise à un crash dans un avenir proche. La récupération complète d'une @try est un mauvais ObjC ; au final, vous devriez toujours relancer l'exception pour permettre au programme de se planter. Votre question est en fait un peu à l'envers, en vous préoccupant des objets non gérés par ARC. À moins que vous ne compiliez en ObjC++, l'ARC fuit intentionnellement comme un tamis après une exception ObjC.

L'approche correcte consiste à éliminer les exceptions. Il ne devrait pas y avoir de chose telle que "Des choses sujettes aux exceptions se passent ici" dans ObjC. ObjC n'est pas (et n'a jamais été destiné à être) un langage à l'abri des exceptions. Lorsqu'il est compilé en tant que ObjC++, un travail supplémentaire est effectué (et un surcoût d'exécution supplémentaire) pour essayer de le rendre plus sûr du point de vue des exceptions, car les exceptions C++ sont courantes, mais cela ne doit pas être considéré comme une raison d'utiliser le langage @try .

L'explication de Clang sur l'ARC avec les exceptions est une excellente introduction au sujet. La section la plus éclairante est la suivante (c'est nous qui soulignons) :

La convention Cocoa standard veut que les exceptions signalent une erreur du programmeur et ne sont pas destinées à être récupérées. Rendre le code sûr pour les exceptions par défaut imposerait des pénalités sévères en termes de temps d'exécution et de taille de code à un code qui ne se soucie généralement pas de la sécurité des exceptions. Par conséquent, le code généré par ARC fuit par défaut sur les exceptions, ce qui est très bien si le processus va être immédiatement terminé de toute façon. Les programmes qui se soucient de la récupération des exceptions devraient activer l'option.

Il est également utile de Sujets relatifs à la programmation des exceptions :

Les cadres Cocoa ne sont généralement pas protégés par des exceptions. Le modèle général est que les exceptions sont réservées aux erreurs du programmeur, et que le programme qui attrape une telle exception doit s'arrêter peu après.

La seule raison d'utiliser @catch c'est parce que vous aimeriez créer une sorte de diagnostic pour vous aider à comprendre le crash (et faire cela correctement est un sujet très avancé qui n'est pas pour les âmes sensibles ou les novices). Il n'est jamais prévu de vous sauver d'une erreur de programmation.

Notez que la fonction @try n'est pas du tout liée à celle de Swift try . Swift try est juste une fantaisie/magie return (il ne s'agit même pas d'une "exception" au sens où on l'entend généralement dans d'autres langues).

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