Problem mit try...except
-
Release() liefert schonmal garkeinen HRESULT zurück, daher ist FAILED(Release()) auch Blödsinn.
COM bietet selbst schon keine Möglichkeit bei "Release()" irgendwelche Fehler zurückzumelden, d.h. es gibt garkeine "Fehlersituation" auf die du im dtor reagieren müsstest.Wenn du mal was anderes schreibst, wo dann im dtor vielleicht Funktionsaufrufe vorkommen können die wirklich Fehlercodes zurückliefern (CloseHandle z.B.), dann ist die Frage nicht so einfach zu beantworten. Schliesslich gibt der dtor das Objekt frei, es existiert danach nichtmehr. Alles was also als unmittelbare Reaktion auf den Fehler passieren soll muss demnach auch im dtor passieren. Eine halbwegs einfache Möglichkeit ist zuzusehen dass im dtor immer nur Code steht der "eigentlich immer funktionieren muss" (wie z.B. CloseHandle mit einem gültigen HANDLE), und im Fehlerfall einfach terminate() aufzurufen.
Fehlerbehandlung in cleanup Code ist aber ein eigenes Thema, und leider nicht ganz trivial.
-
hustbaer schrieb:
Release() liefert schonmal garkeinen HRESULT zurück,...
Was
a) ein guter Hinweis darauf ist, dass die Programmierer sich schonmal an diese "Aufräumen muss klappen"-Maxime gehalten haben (und man das bedenkenlos in seinem Dtor übernehmen kann) und
b) ich natürlich nicht wusste (kenne COM einfach nicht).
Gruß,
Simon2.
-
Ok danke für die Antworten.
Dass ich Release nicht mit FAILED überprüfen muss wusste ich nicht. Wird halt überall geschrieben alles mit FAILED zu überprüfen, von daher dachte ich auch dass Release das benötigt.
@Simon2:
lpdd7 ist eine private Membervariable. Sie stellt eigentlich so das Kernobjekt von der Klasse da. In meiner Klasse ruft bisher keine andere Funktion Release() auf oder setzt auf NULL bis auf den Destruktor. Ich hab das ganze auf NULL gesetzt, weil es ein Pointer ist und das in den Beispielen aus dem Buch auch immer so gemacht wird. Ich denke mal dass lpdd7 bei Release nicht auf NULL gesetzt wird und man das deshalb per Hand macht, damit der Pointer nicht irgendwohin zeigt. Aber keine Ahnung ob ich damit richtig liege...
Ist aber auch nicht Thema dieses Threads.
Deshalb nochmal danke an alle die mir weitergeholfen haben!!!
-
Amateur schrieb:
...
lpdd7 ist eine private Membervariable. ...Damit kann nach Ablauf des Dtors niemand mehr auf sie zugreifen und ihr Wert ist vollkommen irrelevant (bzw. sowieso nicht mehr definiert). Dieses "Setzen auf NULL" ist einen beliebte Technik, um sich eine weitere Information zu merken, ohne ein weiteres Attribut einführen zu müssen: "Zeigt der Zeiger auf etwas Sinnvolles ?" ... brauchst Du aber hier nicht - und hast mich damit in die Irre geführt.

Ist aber wirklich eher eine Kleinigkeit, auf der ich hier nur rumreite, weil ich das Gefühl habe, dass Du mit dem ganzen Thema noch nicht ganz sicher bist und ich Dir dabei helfen möchte, "die richtige Denke" zu entwickeln.
Gruß,
Simon2.
-
Ok alles klar! Danke!
Ja ich hab mich bei dem Design an den Code aus dem DirectX Buch gehalten und war mir nicht sicher ob das NULL setzen wichtig ist. Denn dort wurde es auch so gemacht und zwar in einer Funktion die erst nach der Message Schleife in der WinMain aufgerufen wird. Deshalb dachte ich, dass das NULL setzen einen Sinn hat, da in dem Beispiel danach auch nichts mehr mit lpdd7 passiert...
-
Das Nullsetzen hat dann einen Sinn wenn es die Variable danach noch gibt. Nachdem der dtor gelaufen ist gibt es sie aber nichtmehr. In deinem Buch wird das wahrscheinlich nicht im dtor stehen, daher wird dort auf 0 gesetzt.
(BTW: NULL ist ein C-ismus, und hat in C++ Code IMHO nix verloren, schreib stattdessen einfach 0.)Zu Release(): AddRef() und Release() sind 2 Spezialfälle, die liefern nämlich nen ULONG zurück, der Wert ist der neue Reference-Count des Objektes. (Im Allgemeinen sollte man den Returnwert aber immer ignorieren, max. zum Debuggen "darf" man den noch verwenden. Alles andere ist "böse".) Eine COM Methode kann zwar grundsätzlich verschiedenste Dinge als Returnwert haben, aber bei allen anderen Funktionen hat es sich eingebürgert nen HRESULT zurückzuliefern, und bei "automation kompatiblen" Interfaces ist es AFAIK sogar vorgeschrieben.
Für AddRef() und Release() wurde eine Ausnahme gemacht, die aus verschiedenen Gründen Sinn macht. Und die man sich auch "leisten kann", z.B. da beide keine Fehler zurückzuliefern können brauchen. Bzw. es wäre bei beiden Funktionen sogar ziemlich übel wenn sie Fehler zurückliefern könnten, denn dann müsste man an Stellen Error-Handling machen wo oft garkein vernünftiges Error-Handling möglich ist.
-
Ok...
Auch wenns nicht ganz hier hin passt:
Kann ich dann überall wo ich normalerweise NULL nehme (meistens bei Funktionen als Parameter oder so) 0 verwenden? Wozu gab/gibt es dann die Unterscheidung zwischen NULL und 0? Ich dachte das macht man um zwischen Pointern und dem normalen Wert 0 zu unterscheiden. Ist das in C++ nicht mehr der Fall oder wieso sollte man besser 0 verwenden?
-
Naja, die einzig "unproblematische" Variante NULL in C++ zu definieren ist
#define NULL 0Warum soll ich dann NULL schreiben? Vor allem bietet es keine Sicherheit, ich kann ja in C++ dann genauso sowas schreiben:
int x = NULL;Ich bin mir nichtmal sicher ob NULL offiziell zum C++ Standard gehört...
-
hustbaer schrieb:
Naja, die einzig "unproblematische" Variante NULL in C++ zu definieren ist
#define NULL 0Warum soll ich dann NULL schreiben? Vor allem bietet es keine Sicherheit, ich kann ja in C++ dann genauso sowas schreiben:
int x = NULL;Ich bin mir nichtmal sicher ob NULL offiziell zum C++ Standard gehört...
NULL gehört schon dazu, vermittelt durch die C-Header. Ich halte das Argument auch nicht für ganz stichhaltig. Es gibt schließlich eine Menge Beispiele guter Programmierpraxis, deren Verletzung der Compiler nicht diagnostizieren kann oder darf. Die Verwendung von NULL (so wie wir es heute haben) ist eine Frage der Konvention und richtet sich an den Leser eines Programms, indem sie eine bestimmte Intention ausdrückt.
-
Außerdem kann man ab 2009 in seinen Programmen NULL automatisch durch nullptr ersetzen. Mit der Suchen&Ersetzen-Funktion eures Lieblingseditors.
