Kein RAII - Kein Spaß

Wer “Resource Acquisition Is Initialization” - kurz RAII - nicht kennt, hat nicht das Recht sich als C++ Entwickler zu bezeichnen.

Und selbstverständlich gehört auch die Umkehrung dazu: “Resource Release Is Destruction” - kurz RRID.

Doch die erste Implementierung im GATE Projekt findet in C statt und hier fehlt dieses C++ Konzept wirklich sehr.


In C++ schreibt man sich einmal eine “Smart-Resource” Klasse …

 1class MyResource
 2{
 3private:
 4  resource_type        res;
 5  
 6public:
 7  MyResource()
 8  {
 9    this->res = create_my_resource();
10    if(this->res == NULL)
11    {
12      throw std::runtime_error("Failed to create resouce");
13    }
14  }
15  ~MyResource()
16  {
17    delete_my_resource(this->res);
18  }
19  
20  resource_type get()
21  {
22    return this->res;
23  }
24};

… und diese bindet man dann im Programm ganz natürlich ein:

 1void do_something()
 2{
 3  MyResource res1;
 4  MyResource res2;
 5  MyResource res3;
 6  MyResource res4;
 7  
 8  ...
 9}

Der Programmablauf do_something() sieht damit in C++ sehr sauber aus und der Compiler garantiert die korrekte Freigabe aller Ressourcen.

Aber was tun wir jetzt in reinem C ?

Tja, hier wird oft alles in eine Funktion gepackt. Aber hier müssen wir uns um eine korrekte Ressourcenverwaltung selbst kümmern. Mein alter eingelernter Ansatz sieht dann so aus:

 1int do_something()
 2{
 3  int succeeded = 0;
 4  resource_type res1 = NULL;
 5  resource_type res2 = NULL;
 6  resource_type res3 = NULL;
 7  resource_type res4 = NULL;
 8  
 9  do
10  {
11    res1 = create_my_resource();
12    if(res1 == NULL) break;
13    res2 = create_my_resource();
14    if(res2 == NULL) break;
15    res3 = create_my_resource();
16    if(res3 == NULL) break;
17    res4 = create_my_resource();
18    if(res4 == NULL) break;
19        
20    ...  
21        
22    succeeded = 1;
23  } while(0);
24  
25  if(res1 != NULL) delete_my_resource(res1);
26  if(res2 != NULL) delete_my_resource(res2);
27  if(res3 != NULL) delete_my_resource(res3);
28  if(res4 != NULL) delete_my_resource(res4);
29  
30  return succeeded;
31}

Und jetzt stellen wir uns das Beispiel mit 4 mal so vielen Ressourcen vor …

Dann wird unser do_something() schon ganz schön unübersichtlich. Auch die Frage, an welcher Stelle man eine Funktion “abbrechen” darf, ist in C++ dank Exceptions leichter und schöner beschreibbar, als in C. Und zusätzlich müssen wir uns den uninitialisierten Zustand auch noch irgendwie merken.

Fazit

Schätze deinen C++ Compiler!

Denn im Gegensatz zu uns Programmierern greift er das Thema Ressourcenverwaltung (meist) viel genauer und zuverlässiger auf.