Richtigen Weg, in der Nähe WinAPI Griffe (Vermeidung von wiederholten schließen)
Habe ich einige mit und ich brauchen, um es zu schließen. Es gibt einige stellen im code, wo der Griff wieder geschlossen werden kann. Also, das ist eine richtige Weg, um in der Nähe behandeln?
HANDLE h;
....
if ( h != INVALID_HANDLE_VALUE ) {
::CloseHandle(h);
h = INVALID_HANDLE_VALUE;
}
Es ist eine Frage der bitmap-handles:
HBITMAP hb;
....
if ( hb != INVALID_HANDLE_VALUE ) {
::DeleteObject(hb);
hb = INVALID_HANDLE_VALUE;
}
EDIT: ich denke, es gibt einige Missverständnisse. Ich weiß CloseHandle
ist für das schließen der Griffe. Ich würde gerne wissen, die richtige Art und Weise für das schließen der Griffe. Ähnliche Situationen Auftritt, die mit dem löschen der Zeiger.
Foo *foo = new Foo();
//for example there is 2 functions that can delete foo
void bar() {
....
delete foo;
}
void duck() {
....
delete foo;
}
So, der folgende code bedeutet Probleme:
bar();
duck();
Gibt es einige workaround für diesen Fall. Wir müssen definieren bar
&duck
Funktionen wie diese:
void bar() {
....
if (foo) {
delete foo;
foo = NULL;
}
}
void duck() {
....
if (foo) {
delete foo;
foo = NULL;
}
}
Also, wir vermeiden Sie ein wiederholtes löschen von foo. Die Frage ist, Was ist der richtige Weg, um in der Nähe der Griffe? Ich meine, Wie vermeiden Sie ein wiederholtes schließen Griffen problem?
CloseHandle
ist in der Tat die korrekte Funktion zu nennen, wenn Sie wollen, schließen Sie einen Griff. Aber es gibt einige Ausnahmen, einige Funktionen erstellen behandelt, die geschlossen werden sollten, unterschiedlich. Also entweder zeigen Sie uns, wie das handle erstellt wurde, oder schauen Sie sich auf der MSDN-Website 🙂Der Punkt ist, dass kernel-handles geschlossen mit
CloseHandle
, während andere Griffe (in der Regel GDI-handles) haben Ihre eigene Funktion. Noch auf der MSDN-Seite über die Funktion dient zur Erfassung der Griff ist immer aufgeführt, die die entsprechende Funktion aufrufen, um Sie freizugeben.Die überprüfung und Einstellung für INVALID_HANDLE_VALUE kann gut sein, sinnlos, wenn das handle geschlossen werden kann, aus mehreren Fäden, die Sie benötigen, um vorbereitet zu sein für CloseHandle() nicht ohnehin.
Wenn ein handle geschlossen werden kann von mehreren threads ohne Synchronisation, haben Sie viel schlimmere Probleme als CloseHandle scheitern. Der Griff wiederverwendet wird, indem der kernel und du wirst dann etwas in der Nähe, die Sie nicht beabsichtigen zu schließen. Dieses problem kann sehr schwer aufzuspüren, weil es nie reproduziert die gleiche Weise zweimal.
InformationsquelleAutor Loom | 2012-10-23
Du musst angemeldet sein, um einen Kommentar abzugeben.
Nicht alle Funktionen nutzen
HANDLE
verwendenCloseHandle()
, einige andere schließen Funktionen statt. Auch sind nicht alleHANDLE
Werte verwendenINVALID_HANDLE_VALUE
. Einige verwendenNULL
statt.HBITMAP
nie verwendetINVALID_HANDLE_VALUE
es verwendet immerNULL
. Und Sie sollten nie nennenDeleteObject()
für eineHBITMAP
Sie nicht besitzen.Also die kurze Antwort ist - wenn Sie versuchen, zu erstellen, einige Allgemeine Zweck Griff das management, nicht die Mühe. Sie sind wahrscheinlich, um es falsch. Wenn Sie reservieren/öffnen, einige behandeln, müssen Sie wissen, den richtigen Weg, um es zu schließen, können Sie nicht erahnen.
Wenn Sie möchten, dass die Griffe zu verwalten sich selbst, dann RAII ist die beste Wahl. Ich benutze lieber eine vorgefertigte Klasse, die mit speziellen Eigenschaften zum reduzieren von code-Duplizierung für somit Arten von Griffen, z.B.:
.
.
.
.
Etc.
Der Destruktor hat die Ressource freigeben, falls noch nicht erworben. Ich habe unter anderem Unterstützung für die manuelle Freigabe, weil manchmal ist die Wartezeit für den Destruktor zu spät sein kann, manchmal on-demand-Veröffentlichung ist erwünscht.
Auch sind nicht alle
HANDLE
s sind die Griffe 😉GetCurrentProcess (...)
ist ein no-op auf allen Windows-Versionen, gibt -1. Sie können nicht in der Nähe, die behandeln, ist es sinnlos.Stimmt, aber in diesem Fall würden Sie nicht brauchen, um die Verwendung dieser wrapper für das verarbeiten zu beginnen. Verwenden Sie diese nur für die Griffe, die müssen explizit geschlossen werden.
Ich würde die Bezeichnung RRID (resource Release ist Zerstörung) eher als RAII. Mit RAII, würde ich erwarten, dass Konstruktoren, die die Ressource abrufen (zusätzlich zum Destruktor, gibt es). Ich weiß, nicht jeder zieht, dass die Unterscheidung, aber ich finde es nützlich, zu unterscheiden zwischen streng RAII und übertragen einer Ressource zu einer smartpointer-wie Eigentümer.
InformationsquelleAutor Remy Lebeau
Verwenden RAII pattern.
Wrap Griff in eine Klasse, stellt der Griff in den Konstruktor und zerstört es im Destruktor. Sie finden einige Beispiele in MFC, z.B. Klasse CGdiObject für GDI-Objekte wie
HBITMAP
.Siehe auch diese Frage ALSO: RAII und smart Pointer in C++
Wenn Sie nicht verwenden können, RAII, muss es ein problem mit der Architektur des Programms, wie das Beispiel mit Zeigern zeigt.
Der code mit Zeigern ist nur illustrieren, problem. Tatsächlich, meine Frage ist nicht über Architektur, auch. Anyway, ich danke Ihnen für Ihre Stellungnahme.
RAII kann immer noch verwendet werden, fügen Sie einfach eine Methode der Klasse schließt das aktuelle handle-on-demand, aber immer noch lassen den Destruktor auch in der Nähe der Griff, wenn es nicht bereits erfolgt ist.
Dein "hosting" - Klasse ist nicht die Klasse, die nennen soll
CloseHandle
. Stattdessen fügen Sie eine neue KlasseWin32Handle
, und Ihr hosting-Klasse enthält nun eine oder mehrereWin32Handle
s. Dieses setup ist direkt zu deiner Frage: Es ist dieWin32Handle
Klasse, die verhindert, dass doppelte Schließung. Das schiebt die Verantwortung an einer Stelle der StreuungCloseHandle
alle Anrufe über Ihren code.InformationsquelleAutor Andrey
Ja.
CloseHandle()
schließt windows kernel-Objekt Griffe.DeleteObject()
löscht GDI-Objekte.Ich denke, deine Verwirrung kommt von beiden aufgerufen wird "behandelt", aber Sie sind verschiedene "Klassen" von Objekten. Der Begriff Griff in
HBITMAP
hier verwendet wird, mehr als "opaque identifier". Es gibt auch viele Dokumentationen, die davon ausgeht "Handgriff" == "windows-kernel-Griff".In der Regel, wenn Sie sich Fragen, wie um etwas zu löschen, sollten Sie sich im Konstruktor der Dokumentation.
InformationsquelleAutor cdleonard
Folgende code ist vielleicht, was Sie nach:
Und was machst du mit dem Rückgabewert von Ihrer Funktion? Kochen Sie Sie für das Abendessen?
Verwenden Sie es oder verwenden Sie es nicht. Ich benutze es.
Handle-parameter ist ein Verweis zu HANDHABEN. Wenn Griff ist erfolgreich abgeschlossen dann Griff wird INVALID_HANDLE_VALUE, und der zweite Aufruf ist no-op. Das eigentliche problem ist, wenn Sie zwei Variablen mit dem gleichen handle-Wert und versuchen Sie, schließen Sie beide an. Eine solche situation sollte vermieden werden.
Mein Fehler.
InformationsquelleAutor Dialecticus
Es ist kein RAII, aber es hilft, zu löschen/schließen-handler.
InformationsquelleAutor elszon