Fragensteller
CreateRemoteThread produziert Speicherleck?

Frage
-
Hallo,
ich arbeite zur Zeit mit CreateRemoteThread und zwar muss ich diese funktion dafür nutzen, in einem anderen process von mir hineingeschrieben code auszuführen (code injection).
Das ganze geschieht relativ häufig und der Speicher schnellt deutlich in die Höhe. Dies liegt relativ klar an der funktion CreateRemoteThread, bzw wahrscheinlich wie ich mit dem Handle verfahre.
[DllImport("kernel32.dll")] public static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, out uint lpThreadId); [DllImport("kernel32.dll", SetLastError = true)] public static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds); [DllImport("kernel32.dll")] public static extern bool GetExitCodeThread(IntPtr hThread, out uint lpExitCode);
[DllImport("kernel32.dll")]
public static extern Int32 CloseHandle(IntPtr hObject);
Nutzen tue ich das ganze wie folgt:
IntPtr hThread = WinApi.Kernel.Process.CreateRemoteThread(Handle, IntPtr.Zero, 0, funcHandle, paramPtr, 0, out t); Kernel.Process.WaitForSingleObject(hThread, unchecked((uint)-1)); uint exitCode; Kernel.Process.GetExitCodeThread(hThread, out exitCode); Kernel.Process.CloseHandle(hThread)
- ist ein wenig gekürzte Fassung zwischendurch frag ich auch nach GetLastError ab. Da scheinen aber keine Fehler zu kommen
Das ganze hat einige Auswirkungen. Die Anwendung nutzt im normal Fall ~120mb Speicher. Dadurch das diese funktion in einer schleife ausgeführt wird, ist der speicher nach mehreren Minuten bei über 300mb, lässt man das Program länger laufen kams bei mir bis 1,2gb Ram hoch
Schöne Grüße
Bei CreateThread geschieht übrigends das gleiche- Bearbeitet Madenruffel Freitag, 16. März 2012 01:16
Alle Antworten
-
Hallo Madenruffel,
unter [1] gibt es einen Artikel, der beschreibt, dass die Funktion CreateRemoteThread Memory Leaks verursacht. Allerdings bezieht sich der Artikel auf eine ältere Windows Version, aber ist wahrscheinlich weiterhin für die Funktion relevant.
[1] http://support.microsoft.com/kb/246691
Wir hoffen, vielen Besuchern der MSDN Foren durch das Posten dieses Problems und einer möglichen Lösung weiterhelfen zu können.
Viele Grüße,
Hristo Valev
MSDN Hotline für MSDN Online Deutschland
Disclaimer:
Bitte haben Sie Verständnis dafür, dass wir hier auf Rückfragen gar nicht oder nur sehr zeitverzögert antworten können.
Bitte nutzen Sie für Rückfragen oder neue Fragen den telefonischen Weg über die MSDN Hotline: http://www.msdn-online.de/Hotline
Es gelten für die MSDN Hotline und dieses Posting diese Nutzungsbedingungen, Hinweise zu MarkenzeichenInformationen zur Datensicherheit sowie die gesonderten Nutzungsbedingungen für die MSDN Hotline.
- Bearbeitet Hristo Valev Montag, 19. März 2012 13:26
-
Hallo Hristo,
dass sich ein Fehler aus NT 4.0 Zeiten bis heute durchgemogelt hat, ist äußerst unwahrscheinlich.
Mike Stall zeigt die Verwendung in Using CreateRemoteThread from C#wobei dem Disclaimer gebührende Aufmerksamkeit geschenkt werden sollte:
CreateRemoteThread is evil, could dead-lock, doesn't always work (particularly across-sessions),
and should be avoided in favor or friendlier inter-process communication libraries unless you're a rocket scientist.
Und da Madenruffel nichts zu dem Raketen schreibt, die er dort zünden möchte,
kann die Ursache an allem möglichen liegen, zumal er bei CreateThread die gleichen Probleme hat.Und insoweit nur: Threads in einer Schleife zu erzeugen, sollte man eh vermeiden, denn damit
ist pro Thread schon mal ein MB an Stack reserviert. Siehe u. a. Threads, fibers, stacks and address spaceGruß Elmar
-
Hallo vielen dank für die Antworten, der oben geschriebenen Bericht war mir schon bekannt.Was die CreateRemoteThread funktion, bzw die CreateThread funktion angeht:
Ich programmiere für ein bekanntes Rollenspiel ein Multiplayer. Die Entwickler hatten einen Projekt, der auf diese Weise in ihr Programm eingreift auch schon die Erlaubnis gegeben (das Spiel ist nun rund 8 Jahre alt).
Ich habe ein Hook-System geschrieben um in das Programm reinzukommen, bin mit meinem C# Programm also direkt im Thread. Nun habe ich für die Aufrufe der Funktionen (thiscalls stdcalls usw.) eine funktion geschrieben, die in den speicher eine neue Funktion schreibt, die wiederrum die Funktionen des Spiels aufrufen - Das alles klappt auch wunderbar. Um diese funktionen nun zu starten nutze ich allerdings CreateRemoteThread, warte dann bis es beendet ist und hol mir dann den rückgabewert. (Mach den speicher frei usw. das läuft problemlos solange CreateRemoteThread nicht ausgeführt wird).
Das ganze passiert auch schon wenn die Funktion nur 1 byte groß ist und nur ein return auswirft, liegt also definitv daran, das CreateRemoteThread den speicher nicht wieder frei räumt.
Ich bin ja nicht auf CreateRemoteThread angewiesen - könnte man da auch was mit delegates regeln?
Okay in meinem Fall konnte ich CreateRemoteThread mit
call mc = (call)Marshal.GetDelegateForFunctionPointer(baseadress, typeof(call));
mc();Ersetzen.
- Bearbeitet Madenruffel Dienstag, 20. März 2012 16:38
-
Hallo,
wie angedeutet: Ohne die Umgebung zu kennen kann man fast nichts dazu sagen.
Du wirst Dich schon mit den .NET Interna auseinandersetzen müssen,
denn schon kleine Fehler beim Marshalling können große Auswirkungen haben.Um Probleme rauszufinden wirst Du vermutlich um WinDbg nicht herumkommen,
siehe dazu Intro to WinDBG for .NET Developers
(weitere siehe Google)Da Du "Rollenspiel" schreibst, schau Dir mal andere Projekte an.
Vor längerem hatte ich mir interessehalber den Oblivion Script Extender angeschaut,
wo man auch den Quellcode einsehen kann.
Ein Projekt für den Nachfolger Skyrim gibt es mittlerweile auch, das scheint noch übersichtlicher.Wäre ich nochmal so jung und leichtsinnig ;-)
Wegen des Overheads den .NET naturgemäß mit sich bringt,
würde ich vermutlich komplett zu C++ greifen und alles damit abwickeln.Gruß Elmar
-
Naja meine erste Überlegung war auch c++, da ich mir mit diesem Projekt aber erst die Kenntnisse aneignen wollte, und meine C++ Kenntnisse zusätzlich sehr gering sind, hätte ich mir da 2 Dinge zum lernen aufgehalst, das wollte ich dann doch nicht :P
Inzwischen läufts mit C# doch ganz gut. (Übrigends habe ich ein Konkurrenz Projekt innerhalb 1 Woche aufgeholt... Das andere läuft seit knapp 2 Jahren unter c++)
Den WinDBG werde ich mir noch einmal ansehen.
Wäre ich nochmal so jung und leichtsinnig ;-)
Noch habe ich die Gelegenheit mich solchen Projekten zu witmen :)