Komfortabler Dateimanager mit vielen Funktionen

Shellerweiterungen und CoFreeUnusedLibraries

By Sven on 09.12.2009 - 22:45 in SpeedCommander 13

Ein Anwender hatte mir berichtet, dass SpeedCommander bei ihm nach einer gewissen Inaktivität im Hintergrund bei Aktivierung abstürzt. Der Absturzbericht zeigt dabei folgenden Callstack an:

user32.dll!UserCallWinProcCheckWow()
user32.dll!DispatchMessageWorker()
MxMfc90ud.dll!AfxInternalPumpMessage()
MxMfc90ud.dll!CWinThread::PumpMessage()
MxMfc90ud.dll!CWinThread::Run()

Diesem kann man entnehmen, dass der Absturz während der Verarbeitung einer Nachricht in der Funktion UserCallWinProcCheckWow der user32.dll auftrat. Die Ursache ist aber leider nicht ersichtlich. Kurze Zeit später schrieb mir der Anwender, dass er mit Hilfe von ShellExView den Kontextmenüeintrag von StExBar deaktiviert hat. Anschließend stürzte SpeedCommander nicht mehr ab. Nach der Installation von StExBar konnte ich das Problem nachstellen.

StExBar ist eine Erweiterung für den Explorer und stellt ein Kontextmenü sowie eine Symbolleiste zur Verfügung, in denen häufig verwendete Befehle abgelegt werden können. Der Vertrieb erfolgt unter der GPL, der Quellcode steht somit zur Verfügung. Ich habe mir also den Quellcode heruntergeladen und versucht, mit dem Debugger dem Problem auf den Grund zu gehen.

Meine Vermutung war, dass es etwas mit dem vorzeitigen Entladen der Dll zu tun hat. Dazu muss man wissen, dass eine MFC-Anwendung von Zeit zu Zeit nicht mehr benötigte Handles und temporäre Objekte freigibt. Dies geschieht, wenn die Anwendung Däumchen dreht und auf eine Eingabe des Anwenders wartet. Zu den Aufräumarbeiten gehört es auch, dass in bestimmten Zeitabständen durch Aufruf der Windows-Funktion CoFreeUnusedLibraries nicht mehr benötigte COM-Dlls entladen werden. Zu diesen COM-Dlls zählen auch die verschiedensten Shellerweiterungen.

Beim Entladen einer COM-Dll ruft Windows die von der Dll exportierte Funktion DllCanUnloadNow auf. Durch Rückgabe von S_OK stimmt die Dll einer Entladung zu, mit S_FALSE wird das Entladen verhindert. Nach Änderung des Rückgabewertes auf S_FALSE wurde StExBar nicht mehr entladen und der Absturz in SpeedCommander blieb aus.

Nun galt es, den Grund des Entladeproblems zu finden. StExBar erstellt bei der Initialisierung ein Fenster, in dem eine Symbolleiste und ein Eingabefeld platziert werden. Die Anzeige des Fensters erfolgt im Explorer durch den Aufruf der Schnittstelle IDockingWindow::ShowDW, mit IDockingWindow::CloseDW wird das Fenster wieder entfernt.

SpeedCommander ist allerdings nur an der Anzeige des Kontextmenüs interessiert und nicht an der zusätzlichen Symbolleiste. Das führt dazu, dass das Fenster während der Initialisierung erzeugt, bei der Freigabe des Kontextmenüs aber nicht geschlossen wird. Auch beim Entladen der Dll bleibt das Fenster weiter bestehen, was natürlich nicht beabsichtigt ist.

Bei der Aktivierung von SpeedCommander informiert das Hauptfenster alle untergeordneten Fenster. Dazu gehört auch das unsichtbare Fenster der zwischenzeitlich entladenen StExBar-Dll. Dummerweise ist der Speicherbereich, den die Fensterfunktion belegt hat, durch das Entladen ungültig geworden. UserCallWinProcCheckWow greift so auf einen undefinierten Bereich zu und es kommt zum Absturz. Den vorgeschlagenen Fix hat Stefan schon eingecheckt, vielen Dank dafür an dieser Stelle! Mit der nächsten Version von StExBar sollte das Problem dann nicht mehr auftreten.

Dieses Beispiel zeigt wieder einmal, dass die durch das Entladen von Shellerweiterungen verursachten Abstürze äußerst vielgestaltig und schwer zu ermitteln sind. Deshalb habe ich mich dazu entschlossen, die automatische Entladefunktion in der MFC durch eine Option in der SpeedCommander.ini abschaltbar zu machen. Nun bin ich am Überlegen, ob die Entladefunktion standardmäßig aktiviert (wie bisher) oder deaktiviert werden sollte. Für die Aktivierung spricht, dass nicht mehr benötigte COM-Dlls von Zeit zu Zeit entfernt werden und der Arbeitsspeicher etwas entlastet wird. Die Deaktivierung hat den Vorteil, dass möglicherweise der eine oder andere unerklärliche Absturz der Vergangenheit angehören könnte. Die Tendenz geht im Moment zur Deaktivierung, was meint ihr?

Es gibt 11 Kommentare zu diesem Beitrag

Trackback URL | RSS-Feed für Kommentare

  1. Dieter sagt:

    Ich denke du solltest die Entladefunktion standardmäßig deaktivieren und Windows lieber das Entladen von COM-Dll’s überlassen. In Einzelfällen kann man dann mit der Option in der SpeedCommander.ini immer noch Testen ob die Aktivierung Vorteile bringt.

  2. hanni sagt:

    also bei 4 gb arbeitsspeicher kann das ruhig deaktiviert bleiben.

  3. Racoon sagt:

    Also ich denke auch das es auf ein paar MB RAM mehr oder weniger nicht ankommt

  4. Ulf sagt:

    Ich denke auch, dass die Entladefunktion standardmäßig deaktiviert werden sollte. Beklagt sich ein Nutzer, dass ihm der Speicher vollläuft, kann man ihm evtl. ja immer noch mit der Aktivierung helfen.

  5. Steve Holt! sagt:

    Weiß man denn _ungefähr_, wie sich das typischerweise auf den RAM Verbrauch auswirkt? Ist es nur eine unerhebliche Menge, dann fällt die Entscheidung, es zu deaktivieren, natürlich viel leichter.

  6. Sven sagt:

    Konkrete Tests habe ich noch nicht gefahren, ich habe hier auch recht wenige Erweiterungen installiert. Ich habe die Entladung erstmal deaktiviert, sie kann per SpeedCommander.ini zum Testen auch wieder aktiviert werden.

  7. tbeu sagt:

    Die neue Option als Debugoption ist natürlich praktisch. Das Standardverhalten würde ich nicht verändern. Der Fehler lag ja bei der Shellerweiterung.

  8. Sven sagt:

    Es stimmt schon, dass der Fehler bei der Shellerweiterung lag. Allerdings nützt das dem Anwender wenig, wenn SpeedCommander zwischendurch unerklärlich abstürzt. 🙁

  9. tbeu sagt:

    Deswegen gibt es ja den Debugschalter. Den Firefox starte ich ja auch nicht standardmäßig im abgesicherten Modus.

  10. Sven sagt:

    Mit dem abgesicherten Modus von Firefox hat dies auch nichts zu tun. Der SC verhält sich mit deaktivierter Entladung nun so wie andere Dateimanager (Explorer, TC), die nicht MFC-basiert sind.

  11. tbeu sagt:

    OK.

Top