(gelöst) [WinAPI] Lebensdauer Datei-HANDLE bei Mapping
- Krishty
- Establishment
- Beiträge: 8350
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
(gelöst) [WinAPI] Lebensdauer Datei-HANDLE bei Mapping
Hi,
der übliche Weg, um via WinAPI eine Datei im Speicher abzubilden ist:
HANDLE file = CreateFile()
HANDLE map = CreateFileMapping(file)
void * pointer = MapViewOfFile(map)
und bei der Freigabe umgekehrt:
UnmapViewOfFile(pointer)
CloseHandle(map)
CloseHandle(file)
Meine Frage ist nun: Darf ich file auch sofort wieder schließen, nachdem CreateFileMapping() damit aufgerufen wurde?
Die MSDN scheint sich dazu nicht zu äußern; sie sagt nur, dass sowohl map als auch file wieder freigegeben werden sollten (und zwar möglichst nach pointer, um Speicherlecks zu vermeiden). Bei einem schnellen Test meinerseits schien es keinerlei Probleme zu verursachen.
Falls also jemand Informationen dazu findet, ob der Kernel Reference Count des Datei-HANDLEs durch CreateFileMapping() inkrementiert wird: bitte immer her damit.
Gruß, Ky
der übliche Weg, um via WinAPI eine Datei im Speicher abzubilden ist:
HANDLE file = CreateFile()
HANDLE map = CreateFileMapping(file)
void * pointer = MapViewOfFile(map)
und bei der Freigabe umgekehrt:
UnmapViewOfFile(pointer)
CloseHandle(map)
CloseHandle(file)
Meine Frage ist nun: Darf ich file auch sofort wieder schließen, nachdem CreateFileMapping() damit aufgerufen wurde?
Die MSDN scheint sich dazu nicht zu äußern; sie sagt nur, dass sowohl map als auch file wieder freigegeben werden sollten (und zwar möglichst nach pointer, um Speicherlecks zu vermeiden). Bei einem schnellen Test meinerseits schien es keinerlei Probleme zu verursachen.
Falls also jemand Informationen dazu findet, ob der Kernel Reference Count des Datei-HANDLEs durch CreateFileMapping() inkrementiert wird: bitte immer her damit.
Gruß, Ky
Zuletzt geändert von Krishty am 28.01.2012, 08:43, insgesamt 1-mal geändert.
- dot
- Establishment
- Beiträge: 1746
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: [WinAPI] Lebensdauer Datei-HANDLE bei Mapping
http://msdn.microsoft.com/en-us/library ... 66882.aspx
;)Although an application may close the file handle used to create a file mapping object, the system holds the corresponding file open until the last view of the file is unmapped.
- Krishty
- Establishment
- Beiträge: 8350
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [WinAPI] Lebensdauer Datei-HANDLE bei Mapping
Danke; das hatte ich übersehen.
Allerdings bleibt der Speicher, den man von MapViewOfFile() erhalten hat, nur bis zum Schließen des letzten der beiden HANDLEs freigebbar, und danach hat man zwangsläufig ein Speicherleck.
Sehe ich das soweit richtig?
Also: Die Datei bleibt offen, bis auch die letzte Adresse durch UnmapViewOfFile() freigegeben wurde – das ist an sich erstmal fantastisch.http://msdn.microsoft.com/en-us/library/windows/desktop/aa366532 hat geschrieben:When each process finishes using the file mapping object and has unmapped all views, it must close the file mapping object's handle and the file on disk by calling CloseHandle. These calls to CloseHandle succeed even when there are file views that are still open. However, leaving file views mapped causes memory leaks.
Allerdings bleibt der Speicher, den man von MapViewOfFile() erhalten hat, nur bis zum Schließen des letzten der beiden HANDLEs freigebbar, und danach hat man zwangsläufig ein Speicherleck.
Sehe ich das soweit richtig?
- dot
- Establishment
- Beiträge: 1746
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: [WinAPI] Lebensdauer Datei-HANDLE bei Mapping
Es ist auch nicht ganz klar ob du die Datei gleich nach CreateFileMapping() schließen kannst oder erst wenn das Mapping gemapped wurde. Ich würde mal vermuten dass du sie theoretisch gleich schließen kannst.
Was das Memory Leak angeht bin ich mir nicht ganz sicher was du meinst. So wie ich das verstehe geht's darum, dass du eben UnmapViewOfFile() aufrufen musst bevor du das FileMapping freigibst.
Was das Memory Leak angeht bin ich mir nicht ganz sicher was du meinst. So wie ich das verstehe geht's darum, dass du eben UnmapViewOfFile() aufrufen musst bevor du das FileMapping freigibst.
- Krishty
- Establishment
- Beiträge: 8350
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [WinAPI] Lebensdauer Datei-HANDLE bei Mapping
Ja; so habe ich das auch verstanden.dot hat geschrieben:So wie ich das verstehe geht's darum, dass du eben UnmapViewOfFile() aufrufen musst bevor du das FileMapping freigibst.
Ein schneller Test hat übrigens ergeben, dass der Speicher trotzdem freigegeben wird: Im Fall von
HANDLE file = CreateFile()
HANDLE map = CreateFileMapping(file)
void * pointer = MapViewOfFile(map)
CloseHandle(map)
CloseHandle(file)
// Hier lesbare Daten
before = GlobalMemoryStatusEx().ullAvailVirtual
UnmapViewOfFile(pointer)
delta = GlobalMemoryStatusEx().ullAvailVirtual - before
ist delta exakt so groß wie die Datei, deren Ansicht unmapped wurde.
Das wäre für mich enorm angenehm, weil ich Memory-mapped Files nach ihrer Erzeugung schlicht als Standard-Blobs durch Zeiger und Größe implementieren könnte, ohne mich um Handles kümmern zu müssen. Der Hinweis der MSDN mit dem Speicherleck hinterlässt bei diesem Gedanken aber ein sehr mulmiges Gefühl …
- dot
- Establishment
- Beiträge: 1746
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: [WinAPI] Lebensdauer Datei-HANDLE bei Mapping
Ok, man kann den Satz imo auch so interpretieren, dass man einfach nur Unmappen muss, egal wann...
- Krishty
- Establishment
- Beiträge: 8350
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [WinAPI] Lebensdauer Datei-HANDLE bei Mapping
Dann interpretiere ich ihn sehr gern so :) Danke schonmal; ich brauche ab und an noch Hilfe beim Lesen der MSDN.dot hat geschrieben:Ok, man kann den Satz imo auch so interpretieren, dass man einfach nur Unmappen muss, egal wann...
Anstellen will ich damit das Übliche – man kriegt irgendwo Speicher; arbeitet damit; und gibt ihn wieder frei – egal, ob der Inhalt aus der Exe, von Stapel- oder Freispeicher, oder aus einer Datei kommt.
Dafür muss ich allerdings von einer Basisklasse ableiten, die in bester RAII-Manier sofort mit der fertigen Adresse initialisiert werden will. Da Visual C++ noch keine Delegating Constructors unterstützt und das Initialisieren durch eine freie Funktion eklige Kopier- und Schiebesemantik sowie eine öffentliche struct und einen friend erfordert, habe ich mir bisher durch eine verschachtelte Hierarchie beholfen, bei der die Aufrufreihenfolge Datei öffnen; Ansicht erzeugen; mappen (und das umgekehrte Aufräumen) garantiert ist.
Da ich nun aber nichts mehr außer Adresse und Größe brauche und trotzdem sauber freigeben kann, komme ich mit einer einzelnen direkt abgeleiteten Klasse und einer privaten statischen Funktion aus. Das spart auf einen Schlag fast 3 KiB Maschinentext, die vorher immer durchgelaufen sind. Sehr sehr angenehm.
- Krishty
- Establishment
- Beiträge: 8350
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: (gelöst) [WinAPI] Lebensdauer Datei-HANDLE bei Mapping
Noch ein wenig Gequatsche hinterher:
Mir ist ein Unterschied zwischen CreateFileMappingA() und CreateFileMappingW() aufgefallen:
Mir ist ein Unterschied zwischen CreateFileMappingA() und CreateFileMappingW() aufgefallen:
- Die ANSI-Version führt 20, 30 Befehle auf den Parametern durch und ruft dann das importierte CreateFileMappingNumaW() in KernelBase.dll auf. Dort beginnt das eigentliche Mapping.
- Die UTF-16-Version ist nur ein Platzhalter, der zum aus KernelBase.dll importierten CreateFileMappingW() weiterleitet. Dort wird dann mit dem Mapping begonnen.
- dot
- Establishment
- Beiträge: 1746
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: (gelöst) [WinAPI] Lebensdauer Datei-HANDLE bei Mapping
Das ist nicht verwunderlich, da der Windows Kernel intern UTF-16 basiert ist. Sämtliche ANSI Varianten werden also normalerweise nichts anderes tun als nach UTF-16 konvertieren und dann die Unicode Funktion aufzurufen.
Kanns sein dass CreateFileMappingW() aus der KernelBase.dll selbst auch nur die Numa Funktion aufruft? Denn ansonsten ist das schon etwas merkwürdig.
Achja, bei CreateFileMappingNuma() sagt die MSDN übrigens:
Kanns sein dass CreateFileMappingW() aus der KernelBase.dll selbst auch nur die Numa Funktion aufruft? Denn ansonsten ist das schon etwas merkwürdig.
Achja, bei CreateFileMappingNuma() sagt die MSDN übrigens:
Das dürfte dich etwas ruhiger schlafen lassen ;)To fully close a file mapping object, an application must unmap all mapped views of the file mapping object by calling the UnmapViewOfFile function and then close the file mapping object handle by calling the CloseHandle function.
These functions can be called in any order. The call to the UnmapViewOfFile function is necessary, because mapped views of a file mapping object maintain internal open handles to the object, and a file mapping object does not close until all open handles to it are closed.
- Krishty
- Establishment
- Beiträge: 8350
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: (gelöst) [WinAPI] Lebensdauer Datei-HANDLE bei Mapping
Darum schreibe ich ja; es verwundert auch nicht ;)dot hat geschrieben:Das ist nicht verwunderlich, da der Windows Kernel intern UTF-16 basiert ist. […]
Ich kann nichts derartiges erkennen; der einzige Aufruf geht direkt an __imp_NtCreateSection() (wie auch in CreateFileMappingNumaW()). Es ist möglich, dass das Einrichten der NUMA-Parameter irgendwo im umliegenden Maschinentext geschieht; oder dass der CreateFileMappingNumaW()-Aufruf der ANSI-Version mit Standardparametern geschieht, so dass bei __imp_NtCreateSection() am Ende das selbe ankommt. In diesem Fall würde mich aber wundern, warum es zwei Funktionen unterschiedlichen Namens aber gleichen Zwecks in KernelBase.dll gibt.dot hat geschrieben:Kanns sein dass CreateFileMappingW() aus der KernelBase.dll selbst auch nur die Numa Funktion aufruft? Denn ansonsten ist das schon etwas merkwürdig.
Ohja; perfekt! Verdammt, warum ist diese Information ausgerechnet dort versteckt …dot hat geschrieben:Achja, bei CreateFileMappingNuma() sagt die MSDN übrigens:Das dürfte dich etwas ruhiger schlafen lassen ;)To fully close a file mapping object, an application must unmap all mapped views of the file mapping object by calling the UnmapViewOfFile function and then close the file mapping object handle by calling the CloseHandle function.
These functions can be called in any order. The call to the UnmapViewOfFile function is necessary, because mapped views of a file mapping object maintain internal open handles to the object, and a file mapping object does not close until all open handles to it are closed.