Ich versuche herauszufinden, wie man malloc und verwandte Funktionen in Visual C ++ (2005) global überschreiben kann. Mein Setup ist eine DLL mit statisch verbundener Laufzeitbibliothek, die aus meinem eigenen C ++ - Code, externem C ++ - und C-Code besteht. Was ich erreichen möchte, ist es, einem Benutzer der DLL zu erlauben, ihre eigenen Implementierungen der Speicherzuordnungsfunktionen zu setzen.
Lösungen, die ich nicht verwenden kann:
Dinge, die mich nicht interessieren
Die vernünftigste Lösung, die ich mir vorstellen kann, ist, den Linkprozess irgendwie zu stören und dafür zu sorgen, dass mein eigenes malloc verlinkt wird, vorzugsweise möchte ich die alten malloc-Funktionen als Standard nutzen können .
In Google perf-tools scheint es, als würden sie den Code der Funktionen manuell zur Laufzeit patchen eine Hook-Funktion, die vor dem Aufruf der ursprünglichen Funktion aufgerufen wird. Ist das wirklich der beste Weg, dies zu tun?
Das Folgende trifft auf Linux zu, kann aber auch auf Visual C ++ von Win anwendbar sein.
Die Malloc-Funktion wird von der Systembibliothek glibc bereitgestellt. Die ausführbare Datei ist standardmäßig mit ihr verknüpft.
Wenn das Programm ausgeführt wird, bemerkt der dynamische Lader, dass die ausführbare Datei die malloc-Funktion benötigt und nach der ersten Bibliothek sucht, die diese Funktion bereitstellt.
Da glibc (standardmäßig) das letzte in dieser Liste ist, ist die gefundene Bibliothek möglicherweise nicht glibc.
Sofern Sie glibc nicht statisch in die ausführbare Datei eingebunden haben, besteht die offensichtliche Lösung darin, die ausführbare Datei mit der Bibliothek zu verknüpfen, die Ihr eigenes malloc bereitstellt, und sicherzustellen, dass sie die Systemdatei außer Kraft setzt.
Ich bin auch daran interessiert, eine saubere Lösung dafür zu finden. Wir kompilieren für mehrere Plattformen, also können wir auf der Nicht-Windows-Seite der Dinge - wrap glücklich verwenden. Wir müssen nur die Ersatzfunktionen erstellen und alles funktioniert ohne Fehler oder Hacks.
Auf der Windows-Seite der Dinge überschreiben wir die malloc-Aufrufe, aber verwenden dann /FORCE:MULTIPLE
, um mit den Linker-Fehlern umzugehen. Es funktioniert, die Speicherfunktionen werden aufgerufen und alles wird verfolgt, aber es fühlt sich an wie ein Hack.
Von MSDN:
A file created with this option may not run as expected. The linker will not link incrementally when the /FORCE option is specified.
Es fühlt sich nicht nur an wie ein Hack, es tötet, bearbeitet und geht weiter.
Die /FORCE:MULTIPLE
-Option könnte deine Probleme beheben, aber ich sage es nicht als Heilmittel, ich versuche immer noch, das zu finden.
: D
Eine Lösung, die ich verwendet habe, besteht darin, die Visual C ++ C-Laufzeitbibliothek (crt) aus dem Quellcode wiederherzustellen.
Es kann hier in diesem Ordner gefunden werden:
C: \ Programme \ Microsoft Visual Studio 9.0 \ VC \ crt
Stellen Sie sicher, dass Sie die Visual Studio-Eingabeaufforderung starten, um sie zu erstellen. Das Ausführen von nmake reicht aus, um den Aufbau zu starten, obwohl Sie vielleicht herausfinden möchten, welches Ziel Sie erstellen sollen. Das bedeutet, dass Sie das Makefile verstehen müssen.
Es kann eine Anstrengung sein zu verstehen, wie man den CRT erstellt, aber sobald Sie es bauen, können Sie Ihren eigenen Code in malloc hinzufügen, frei und realloc, etc.
Leider habe ich ein Gerücht gehört, dass wir nicht in der Lage sein werden, den crt aus dem Quellcode ab Visual Studio 2010 zu erstellen.
Leider weiß ich nicht genug über den Microsoft Linker. Aber ich habe '--wrap', was du für alles wie malloc oder frei oder irgendetwas anderes (ich tue das) verwenden kannst.
Alle Aufrufe von malloc werden zu einer Funktion namens __wrap_malloc umgeleitet, die Sie implementiert haben. Sie können dann Real malloc mit __real_malloc aufrufen. Dies hat den Vorteil, dass auch in externen Bibliotheken verwendete mallocs erfasst werden. Ich bin sicher, dass der Microsoft-Linker eine ähnliche Funktion haben könnte.
Entfernen Sie alle OBJ-Dateien, die Speicherverwaltungsfunktionen enthalten, aus den Laufzeitbibliotheken mithilfe des LIB-Tools, verwenden Sie dann die Option "Standardbibliotheken ignorieren" in der IDE und geben Sie stattdessen manuell "Ihre" Laufzeitbibliothek an. Dann kompilieren; Sie sollten ein paar Linker-Fehler über undefined malloc
und free
und so weiter bekommen. Hier kommst du rein!
(Wahrscheinlich werden Sie auch etwas Ähnliches wie die C ++ - Bibliotheken machen wollen, wenn Sie sie verwenden, obwohl ich denke, dass der Standard operator new
s Aufruf malloc
ist, damit Sie sofort loslegen können.)
Die Visual Studio-Installation wird mit dem Laufzeitquellcode geliefert (suchen Sie in vc/crt/src
in Ihrem Visual Studio-Installationsordner), sodass das Auffinden der vollständigen Speicherverwaltungsfunktionen ziemlich einfach ist. Ich habe keine genauen Details zur Hand (früherer Arbeitgeber ...), aber soweit ich mich erinnere, dauerte es nur einen halben Tag, um zu sortieren, obwohl es mehr Speicherzuweisungsfunktionen gab, als ich erwartet hatte.