Zum Schließen der Verbindungen zu Datenbanken wird der Mechanismus der Finalisierung verwendet (siehe [Tem94]). Es wird für die Anweisungs- und Verbindungsobjekte jeweils eine Prozedur registriert, die aufgerufen wird, wenn der Garbage-Collector den Speicher zur Wiederverwendung einsammelt. In der Abbildung sieht man, daß jede Anweisung einen Verweis auf die darunterliegende Verbindung hat, Verbindungsobjekte werden also sicher nicht vor den Anweisungsobjekten freigegeben. Es kann aber sein, daß Verbindungsobjekte nur mehr von Anweisungsobjekten referenziert werden, daß also beide (Verbindung und Anweisung) im selben Garbage-Collector-Lauf eingesammelt (und somit finalisiert) werden. In den Finalisierungsprozeduren der Anweisungs- und Verbindungsobjekte werden ODBC-Funktionen aufgerufen, die Speicher innerhalb des Datenbanktreibers freigeben. Beim Aufruf dieser Funktionen muß man darauf achten, daß zuerst der Speicher für die Anweisungen freigegeben wird und dann erst der Speicher für die Verbindung. Wird der Speicher für Anweisungen nicht explizit freigegeben, wird er spätestens beim Freigeben des Speichers für die Verbindung (automatisch vom Datenbanktreiber) freigegeben. Da keine Reihenfolge der Finalisierung der Oberon-Objekte definiert ist und es möglich ist, daß die Finalisierungsprozedur der Anweisungen nach der der Verbindungen aufgerufen wird, darf man in diesem Fall (der Speicher für die Anweisungen ist ja implizit beim Freigeben des Speichers für die Verbindung schon freigegeben worden) die ODBC-Funktion zum Freigeben des Anweisungsspeicher nicht mehr aufrufen. Macht man das trotzdem, resultiert daraus eine Speicherschutzverletzung.
VAR ret: INTEGER; c: Connection;
BEGIN
c := o(Connection);
ret := ODBC.SQLDisconnect(c.dbc);
ret := ODBC.SQLFreeConnect(c.dbc);
c.finalized := TRUE
END FinalizeConnection;
PROCEDURE FinalizeStatement (o: S.PTR);
VAR ret: ODBC.Retcode; s: Statement;
BEGIN
s := o(Statement);
IF
END FinalizeStatement;
nn¯
PROCEDURE FinalizeConnection (o: S.PTR);
~
s.conn.finalized THEN ret := ODBC.SQLFreeStmt(s.stmt, ODBC.Drop) END