Definire l'allocazione delle risorse nella documentazione del metodo

0

Voglio scrivere una libreria con la funzione "nessuna garanzia di perdita di risorse". Quindi saprò se ogni metodo assegna o meno una risorsa. Potrebbe cambiare il codice. Ad esempio:

void foo()
{
  methodDontAllocateAnyResources();
  methodCanThrow();
}

void bar()
  methodAllocateSomeResources();
  try{
    methodCanThrow();
  }
  catch(const std::exception& exp){
    releaseAllocatedResources();
    throw;
  }
}

Entrambe le funzioni foo () e bar () possono generare un'eccezione. Non importa perché faccio propagare le eccezioni. Ma in bar (), devo rilevare una possibile eccezione per evitare una perdita di risorse.

Nell'esempio potrei decidere di usare o meno un blocco try-catch facilmente. Tuttavia, sai, normalmente non possiamo capire se un metodo assegna o meno una risorsa con il suo nome. Quindi, ho deciso di mettere queste informazioni nella documentazione del metodo. Doxygen non ha un tale tag. Inoltre, non riesco a trovare alcuna risorsa web che lo suggerisca. Pensi che l'utilizzo di un tag personalizzato @ assegnazione risorse sia una buona idea?

Grazie

    
posta Q Q 07.01.2015 - 10:23
fonte

3 risposte

1

I want to write a library with "no resource leak guarantee" feature. [...] It doesn't matter because I let exceptions to propagate. But In bar(), I must catch a possible exception to avoid a resource leak.

Questo suona bene, fino all'ultima frase.

Considera di utilizzare le risorse RAII e i tipi di ritorno più intelligenti per gestire le risorse, anziché i blocchi try / catch interni.

Implementazione alternativa per bar :

struct raii_resource {
{
  raii_resource(type value) : value_{value} {}
  ~raii_resource() { releaseAllocatedResources(value_); }
  type value_;
}; 

void bar() {
  raii_resource r = methodAllocateSomeResources(); // returns type instance
  methodCanThrow();
}

Se la tua funzione ha bisogno di restituire la risorsa assegnata al codice client, basta semplicemente avvolgere il valore restituito in uno smart wrapper (che verrà eliminato alla fine dell'ambito).

Di solito, in C ++ dovresti usare solo i blocchi try / catch per gestire gli errori, non per rilasciare le risorse allocate.

Se lo fai (usa raii), la documentazione delle risorse allocate diventerà irrilevante, perché le perdite di risorse non sono più possibili.

Detto questo, per aggiungere le informazioni sulle allocazioni alla documentazione dell'API, vorrei aggiungerlo come @remarks o qualcosa di simile.

    
risposta data 07.01.2015 - 12:02
fonte
1

il tuo obiettivo: "nessuna garanzia di perdita di risorse"

la tua soluzione preferita: utilizzare un tag personalizzato @ allocazione risorse per documentare tutte le possibili allocazioni di risorse

Non credo che l'idea di documentare l'allocazione delle risorse ti aiuterà a evitare perdite di risorse.

le probabilità che tu abbia dimenticato di aggiungere la risorsa-il tag della documentazione è alto quanto la possibilità che ti dimentichi di rilasciare una risorsa in un blocco o blocco finale.

Da parte mia, sarebbe meglio avere un modo dichiarativo per evitare perdite di risorse come c ++ puntatori intelligenti .

java e c # hanno un costrutto dichiarativo del linguaggio "using" che si occupa del deal-deal delle risorse:

 using (MyResource r = new MyResource()) {
    doSomeThingWith(r);
 }

Il compilatore lo traduce in qualcosa di simile (sintassi java, la sintassi c ++ dovrebbe essere simile)

 MyResource r = null;
 try {
    r = new MyResource();
    doSomeThingWith(r);
 } finally {
    if (r != null) delete r;
 }

Non so se c'è qualcosa di simile a "usare" nel mondo c ++.

    
risposta data 07.01.2015 - 11:33
fonte
0

Semplicemente aggiungendo tag dove si assegnano risorse solo documenti in cui è probabile che si verifichi la perdita. In realtà non impedisce la perdita.

Usa RAII quando assegni risorse perdibili: acquisiscile solo nei costruttori, quindi liberali nei distruttori corrispondenti. Fai attenzione ai costruttori che possono lanciare eccezioni. Aggiungete gestori di eccezioni all'interno del costruttore per riordinare le risorse già acquisite, oppure avvolgete ogni risorsa in una classe semplice che esegue il proprio RAII.

Attenzione ai puntatori grezzi - quando un puntatore esce dall'ambito, non rilascia la cosa a cui punta. Preferisci archiviare le tue risorse RAII in base al valore o utilizzare puntatori intelligenti che libereranno la cosa a cui puntano.

    
risposta data 07.01.2015 - 13:45
fonte

Leggi altre domande sui tag