3 votes

Les RAII basés sur la pile sont-ils garantis d'être exécutés uniquement après être sortis de la portée en C++ ?

Lorsque vous utilisez L'acquisition des ressources est l'initialisation (RIAA) En C++, il est courant d'avoir quelque chose comme ceci :

class CriticalSection {
public:
    void enter();
    void leave();
};

class SectionLocker {
public:
    SectionLocker(CriticalSection& cs)
    : mCs(cs) {
       cs.enter();   
    }

    ~SectionLocker() {
        cs.leave();
    }

private:
    CriticalSection& mCs;
};

CriticalSection gOperationLock; // Global lock for some shared resource

void doThings(int a, int b) {
    SectionLocker locker(gOperationLock);
    int c = doOtherThings(a);
    doMoreThings(b);
    doOneMoreThing(a, b, c);
}

Je sais que dans certains langages à ramassage d'ordures (comme le CLR), l'une des nombreuses raisons pour lesquelles cette méthode n'est pas sûre est que l'objet locker dans doThings() peut être ramassé avant le retour de doThings(), car locker n'est jamais référencé après sa création.

Le comportement attendu, à savoir que le destructeur de locker ne soit appelé qu'après l'appel à doOneMoreThing(), est-il bien défini en C++ ?

Si c'est le cas, y a-t-il des garanties sur le moment où le destructeur sera appelé (et où gOperationLock sera libéré) ? Ou est-ce seulement à un moment donné après qu'il soit sorti du champ d'application ?

7voto

Flexo Points 39273

La norme C++ (n3290) est assez claire à ce sujet. Vos objets RAII auront toujours une durée de stockage automatique (si ce n'est pas le cas, vous vous y prenez mal !).

Le §12.4.11 dit :

"Les destructeurs sont invoqués implicitement .... pour les objets construits avec une durée de stockage automatique (3.7.3) lorsque le bloc dans lequel un objet est créé sort (6.7)"

Le §6.7.2 dit :

Les variables avec une durée de stockage automatique déclarées dans le bloc sont détruites à la sortie du bloc (6.6)

et le §6.6.2 indique :

Lors de la sortie d'une portée (quelle que soit la manière dont elle a été réalisée), les objets dotés de la fonction automatique de stockage automatique (3.7.3) qui ont été construits dans cette portée sont détruits dans l'ordre inverse de leur construction.

L'ensemble de ces éléments ne laisse aucun doute sur le fait que la seule façon conforme d'implémenter ce système est que le comportement observable soit que les objets de stockage automatique soient détruits à la fin d'un bloc.

3voto

Mike Seymour Points 130519

Il est très bien défini en C++, ce qui explique pourquoi le RAII fonctionne. Tous les objets automatiques sont détruits au moment où ils sortent de leur portée, dans l'ordre inverse de leur construction.

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