Ressourcenbelegung ist Initialisierung, meist abgekürzt durch RAII (englisch: resource acquisition is initialization), bezeichnet eine in bestimmten Programmiersprachen (wie z. B. C++) verbreitete Programmiertechnik zur Verwaltung von Betriebsmitteln (auch Ressourcen genannt). Dabei wird die Belegung von Betriebsmitteln an den Konstruktoraufruf einer Variablen eines benutzerdefinierten Typs und die Freigabe der Betriebsmittel an dessen Destruktoraufruf gebunden. Die automatische Freigabe wird beispielsweise durch das Verlassen des Gültigkeitsbereichs ausgelöst (am Blockende, bei Ausnahmeauslösung, durch Rückgabe an den Aufrufer usw.), der implizite Destruktoraufruf der Variablen sorgt dann für die Wiederfreigabe der Ressource.

Anwendung

Bearbeiten

Typische Einsatzfälle für RAII sind die Steuerung von Prozess- oder Thread-Sperren in nebenläufigen Programmen und die Verwaltung von Datei-Operationen. Da Destruktoren auch unter Ausnahmebedingungen automatisch aufgerufen werden, ist RAII auch ein Schlüsselkonzept zum Schreiben von ausnahmefestem Code.

Zu den Programmiersprachen, die die Anwendung der Programmiertechnik RAII ermöglichen, gehören beispielsweise C++, Ada, D und Rust. In C# oder Java ist diese Technik dagegen nicht direkt möglich, da dort die Destruktion aller Objekte von einem nebenläufigen Garbage Collector verwaltet wird (siehe Abschnitt Varianten).

Beispiel

Bearbeiten

Das folgende Beispielprogramm ist in der Programmiersprache C++ verfasst:

#include <string>
#include <cstdio>

class Datei {
    FILE* datei_;

public:
    Datei(const std::string& name)
    : datei_( std::fopen(name.c_str(), "w+") ) {} // Öffnen der Datei

    ~Datei() {
         std::fclose(datei_); // Schließen der Datei
    }

    void ausgeben(const std::string& text) {
        if (datei_)
            std::fputs(text.c_str(), datei_);
    }
};

int main() {
    Datei datei("aufzeichnung.txt"); // Öffnen der Datei (Anfordern der Ressource)
    datei.ausgeben("Hallo Welt!");

    // Mit dem Ende der Funktion endet auch der Gültigkeitsbereich (Scope)
    // des Objekts datei. Daher wird der Destruktor Datei::~Datei()
    // aufgerufen, der die Datei schließt → Freigabe der Ressource.
}

Zweites Beispiel

Bearbeiten

nicht RAII:

void func(void)
{
    char* buffer = new char[3];
    buffer[0] = 'A';
    buffer[1] = 'B';
    buffer[2] = 'C';

    // buffer verwenden

    delete[] buffer;
}

RAII:

void func(void)
{
    std::vector<char> buffer = {'A', 'B', 'C'};

    // buffer verwenden   
}

Varianten

Bearbeiten

Das korrekte Funktionieren dieser Technik hängt wesentlich von den Eigenschaften der Konstruktoren und Destruktoren der Sprache ab. In C++ wird durch den Sprachstandard garantiert, dass ein Objekt beim Durchlaufen seiner Deklaration erstellt und dabei sein Konstruktor aufgerufen wird. Beim Verlassen seines Gültigkeitsbereichs muss das Objekt zerstört werden, d. h. sein Destruktor wird aufgerufen und kann die Freigabe von Ressourcen veranlassen.[1] Dass ein Destruktor aufgerufen wird, kann allerdings in keiner Programmiersprache garantiert werden, da Programme immer abnormal (z. B. durch Stromausfall oder SIGKILL) beendet werden können. In solchen Fällen kann allerdings keine Programmiertechnik die korrekte Freigabe der Ressourcen sicherstellen.

Programmiersprachen mit Garbage Collection, wie z. B. C# oder Java, machen keine Garantien bezüglich des Zeitpunkts, zu dem ein nicht mehr referenziertes Objekt durch den Garbage Collector freigegeben wird. Dieser Zeitpunkt, zu dem ein Objekt zerstört und die Finalisierungsmethode aufgerufen wird, ist bei nebenläufiger Garbage Collection auch nicht mehr deterministisch. Dadurch kann das Objekt eine Ressource länger belegen als eigentlich erwartet, insbesondere auch über seinen Gültigkeitsbereich hinaus. Allgemein kann dieses Problem nur umgangen werden, indem explizit eine Funktion zur Freigabe der Ressourcen aufgerufen wird und/oder spezielle Sprachkonstrukte verwendet werden.[2][3][4]

Die für C# empfohlene Alternative ist die Implementierung des System.IDisposable-Interfaces – auch Dispose Pattern genannt. Bei Verwendung des using-Blocks wird sichergestellt, dass die Methode Dispose() am Ende dieses Blocks aufgerufen wird, um belegte Ressourcen zu einem definierten Zeitpunkt freizugeben.

In Java kann mithilfe der try-with-resources-Anweisung ähnlich sichergestellt werden, dass Ressourcen am Ende eines Gültigkeitsbereichs in umgekehrter Reihenfolge wieder freigegeben werden.[5][6]

Bearbeiten

Einzelnachweise

Bearbeiten
  1. Bjarne Stroustrup: Die C++-Programmiersprache. 4. aktualisierte und erweiterte Auflage. Addison-Wesley, München/Boston 2000, ISBN 3-8273-1660-X, S. 259 f., S. 390 f.
  2. Christian Nagel, Bill Evjen, Jay Glynn, Karli Watson, Morgan Skinner: C# 2012 and .NET 4.5. John Wiley & Sons, Indianapolis 2013, ISBN 978-1-118-31442-5, S. 353 ff.
  3. Allen Jones, Adam Freeman: Visual C# 2010 Recipes. A Problem-Solution Approach. Apress Springer, New York 2010, ISBN 978-1-4302-2525-6, S. 647 ff.
  4. Frank Eller: Visual C sharp 2010. Pearson Deutschland, München 2010, S. 200 f.
  5. Oracle Java Tutorial: The try-with-resources Statement
  6. Java Language Specification: Chapter 14, Blocks and Statements, try-with-resources

📚 Artikel Terkait di Wikipedia

Abkürzungen/Luftfahrt/E–K

Quecksilbersäule (siehe auch Torr) INIT Initial Anfangs-… INIT Initialize, Initialization initialisieren (Eingabeseite im FMS) INIT FL Initial Flight Level vorgesehene

Initialisierungsdatei

Google-Buchsuche): “First, some background. Many applications need to store program initialization or configuration data.”  Mark Minasi, Eric Christiansen, Kristina Shapar:

Ethernet

Sercos III 0x88E1 HomePlug AV 0x88E5 MACsec 0x8906 Fibre Channel over Ethernet 0x8914 FCoE Initialization Protocol (FIP) 0x8947 GeoNetworking protocol

Singleton (Entwurfsmuster)

kontrollieren. Die Konfiguration des Singletons ist – zumindest bei Lazy-Initialization (s. u.) – nur über andere Singletons möglich, zum Beispiel Environment-Variablen

Liste der Portnummern

for Media Management Systems (MMS) Session Security, Authentication, Initialization Protocol (SSAIP) (Memento vom 12. April 2010 im Internet Archive) RFC:

Initialization-on-demand holder idiom

In der Softwareentwicklung bezeichnet das Entwurfsmuster Initialization on Demand Holder eine Implementierungsmöglichkeit eines sogenannten Lazy-Initialisierten

Evolutionärer Algorithmus

  Borhan Kazimipour, Xiaodong Li, A. K. Qin: A review of population initialization techniques for evolutionary algorithms. IEEE, 2014, ISBN 978-1-4799-1488-3

Real-Time Streaming Protocol

Transportinformationen, die zwischen Client(s) und Servern transferiert werden. Media Initialization Beinhaltet den Datentyp/Codec (H.264). Außerdem z. B. Zeitangaben, Farbsignale