![]() |
FastMM4 und Delphi 7
Ich möchte FastMM4 mit Delphi 7 verwenden und habe eine große Applikation. Ich schreibe FastMM4 als erstes USES im meine .dpr.
Egal, was ich mache, in der system.pas wird schon Speicher mit dem alten MemoryManager alloziert, sodass FastMM4 nicht startet. Ich habe mit Debug-DCUs kompiliert und komme mit [F7] direkt in der SysInit.pas rein. Der angezeigte SysInit.pas-Quelltext stimmt aber scheinbar nicht mit der verwendeten DCU überein, der Debugger springt in Zeilen, die meines Erachtens nicht die real verwendeten sind. Ich kann also nicht nachvollziehen, was da wirklich passiert. Ich dachte mir, kompiliere doch die system.pas mit ihrer SysInit.pas neu und das funktionierte auch: "C:\Program Files (X86)\Borland\Delphi3\Bin\DCC32.EXE" -$D+ -Y SYSTEM und ohne Debug-Info: "C:\Program Files (X86)\Borland\Delphi3\Bin\DCC32.EXE" -$D- -Y SYSTEM Die entstandenen DCUs habe ich in die Verzeichnisse "C:\Program Files (x86)\Borland\Delphi7\Lib\Debug" und "C:\Program Files (x86)\Borland\Delphi7\Lib". Ich glaube auch, dass der VirtualStore mir keine Streiche spielt, weil er für meinen Benutzer an dieser Stelle leer ist. Es ändert sich aber nichts. Der Debugger springt wild in SysInit.pas und System.pas herum. Irgendwas reserviert dort dann Speicher mit dem alten MemoryManager und FastMM4 quittiert den Dienst. Mit den mitgelieferten Demo-Programmen funktioniert der FastMM4. Ich wäre dankbar für jeden Hinweis! |
AW: FastMM4 und Delphi 7
Ich hab grade nur 'nen FastMM4 von 2007 hier rumliegen, aber da wird sich wohl nicht viel geändert haben.
Zitat:
Aktiviere mal UseOutputDebugString, starte dein Programm im Debugger und schau was im Log passiert. |
AW: FastMM4 und Delphi 7
Danke für Deine Antwort! Ich hatte vorher schon über OutputDebugString gelesen, aber ich habe keine Ahnung wie ich das aktiviere und wo ich dann das Log lesen kann. Googeln hat mir eben nichts recht gebracht. Vielleicht kannst Du mir nochmal mit den Debug-Logs auf die Sprünge helfen!
Ich habe in der system.pas debuggt und festgestellt, dass der FastMM4 wahrscheinlich in der Schlange der Units nicht vorne initialisiert wird, sondern halt zu spät. Obwohl in der *.dpr das FastMM4 zuerst eingetragen ist. Gibt es sonst einen Grund, warum andere Sachen zuerst initialisiert werden? Z.B. die Textressourcen werden anscheinend zuerst gelesen. Bei den Demo-Programmen von FastMM4 kommen die erst später dran. Ich könnt' in die Tischplatte beißen :-D |
AW: FastMM4 und Delphi 7
Der Compiler geht die Uses-Liste in der DPR und dann in den verlinkten Units durch. Die Units in der DPR werden der Reihe nach initialisiert, außer in einer der Units wird wiederrum was eingebunden, was eventuell auch in der DPR steht, dann wird das natürlich vorgezogen.
Das Erste in der DPR kann also nur als Erstes kommen. Und da FastMM außer den System-Units, der Windows.pas (was sonst nichts einbindet und keine Initialization besitzt) und seinen eigenen Units nichts einbindet, muß FastMM auch als Erstes geladen werden, wenn es in der DPR das Erste ist. Vorher gibt es nur die zwei System-Units, welche immer automatisch zuerst eingebunden werden, also System.pas und SysInit.pas. Bei Delphi 7 und Davor gibt es nur eine "Ausnahme" ... hast du dir vielleicht den Delphi 7-Virus eingefangen? Für Delphi 7 gibt es einen "Test"-Virus der die System.pas ändert und neu kompiliert, denn blöder Weise arbeiten viele als Administrator und wenn nicht, dann haben sie dem Programmverzeichnis Schreibrechte gegeben, damit Delphi 7 immernoch funktioniert, da es im Programmverzeichnis rumschreibt. :stupid: |
AW: FastMM4 und Delphi 7
Genau so sollte es sein. Isses aber leider nicht :shock: FastMM4 kommt trotzdem später...
Kannst Du mir bitte nochmal einen Hinweis zu dem UseOutputDebugString geben? Wie aktiviere ich das? Wo und wie kann ich das Log lesen? |
AW: FastMM4 und Delphi 7
Aktivieren: in der Options-INC des FastMM :zwinker:
OutputDebugString wird an den Debugger geschickt, wenn Einer verbunden ist. (Programm im Debugger gestartet) Und Delphi schreibt das dann ins Ereignisprotokoll, welches in der Debug-Ansicht standardmäßig angezeigt wird. (Ansicht > Debugfenster > Ereignisprotokoll) |
AW: FastMM4 und Delphi 7
Danke. Hab' das {$define UseOutputDebugString} aktiviert. Hilft aber auch nix, der FastMM4 wird ja gar nicht erst lebendig :cyclops:
Mir gehen die Ideen aus, wie ich die Reihenfolge der Units beeinflussen könnte. Einen Virus habe ich wahrscheinlich nicht. Mein Avira würde den wahrscheinlich entdecken und als Admin habe ich das Delphi nur einmal gestartet nach der Installation. Jetzt gehe ich erst mal ratlos zu Bett... Danke Dir für Deine Unterstützung! |
AW: FastMM4 und Delphi 7
Warum da noch selbst mit den Directiven rumspielen verwende doch einfach FastMM4Options
![]() gruss |
AW: FastMM4 und Delphi 7
Ich habe das Problem auf eine sehr spezielle Art gelöst. Es bleibt dabei, bei meinen über hundert Units wird FastMM vom Compiler nicht an der frühen Stelle initialisiert, sondern erst nachdem andere Units schon Speicher vom alten MemoryManager angefordert haben. FastMM4 tritt daher so seinen Dienst nicht an. Die Reihenfolge wird vom Compiler festgelegt, so dass man zunächst keine Möglichkeit hat einzugreifen. Aber es geht doch :-D
Ich habe nämlich 2 Änderungen gemacht:
Zu 1.: Die FastMM4.pas sieht am Ende jetzt also so aus:
Delphi-Quellcode:
Die 4 NOPs ergeben 4 x $90 also ein DWORD $90909090 im Code. Daran kann man diese Unit in der Liste erkennen.
initialization
asm NOP NOP NOP NOP end; RunInitializationCode; finalization {$ifndef PatchBCBTerminate} FinalizeMemoryManager; {$endif} end. Zu 2.: Der Compiler legt im Quellcode eine Liste an, die aus je 2 Pointern auf Prozeduren für jede Unit besteht: Init für die Initialisierung und FInit für die Finalisierung. Bevor beim Programmstart nun alle Units nacheinander in InitUnits in system.pas initialisiert werden, suche ich zuerst nach meinem Eintrag mit $90909090. Die Nummer in der Liste merke ich mir dann in der Variablen iFastMM4. Beim Initialisieren wird die Liste vorwärts abgearbeitet, beim Finalisieren rückwärts. Wenn die 5. Unit dran wäre, initialisiere ich dann immer erst die FastMM4. Wenn die FastMM4 regulär dran wäre ignoriere ich sie. Beim Finalisieren, wie gesagt, genau anders herum:
Delphi-Quellcode:
Die system.pas muss man manuell im CMD-Fenster mit dem Kommandozeilencompiler DCC32 kompilieren:
VAR iFastMM4:LongInt=-1; {Falls die Unit FastMM4 früher behandelt werden muss}
procedure FinalizeUnits; var i,Count: Integer; Table: PUnitEntryTable; P: Pointer; begin if InitContext.InitTable = nil then exit; Count := InitContext.InitCount; Table := InitContext.InitTable^.UnitInfo; try FOR i:=Count-1 DOWNTO 0 DO BEGIN InitContext.InitCount:=i; IF i=iFastMM4 THEN Continue; P:=Table^[i].FInit; IF Assigned(P) THEN TProc(P)(); IF (i=5) AND (iFastMM4>-1) THEN BEGIN InitContext.InitCount:=iFastMM4+1; TProc(Table^[iFastMM4].FInit)() {erst die 5, dann FastMM4} END; END; except FinalizeUnits; { try to finalize the others } raise; end; end; const errCaption: array[0..5] of Char = 'Error'#0; {***********************************************************} procedure InitUnits; var Count,i: Integer; Table: PUnitEntryTable; P,P1: Pointer; begin if InitContext.InitTable = nil then exit; Count := InitContext.InitTable^.UnitCount; Table := InitContext.InitTable^.UnitInfo; {$IFDEF LINUX} Inc(Cardinal(Table), InitContext.Module^.GOT); {$ENDIF} try FOR i:=0 TO Count-1 DO BEGIN {Unit FastMM4 suchen} P:=Table^[i].Init; IF Assigned(P) THEN BEGIN P1:=P; Inc(DWord(P1),9); IF DWord(P1^)=DWord($90909090) THEN BEGIN {Initialisierung der Unit FastMM4 gefunden! (muss dort mit ASM NOP NOP NOP NOP END anfangen! NOP=$90)} IF I<=7 THEN Break; iFastMM4:=I; Break; END; END; END; FOR i:=0 TO Count-1 DO BEGIN InitContext.InitCount:=i+1; IF i=iFastMM4 THEN Continue; IF (i=5) AND (iFastMM4>-1) THEN BEGIN InitContext.InitCount:=iFastMM4+1; TProc(Table^[iFastMM4].Init)() {erst FastMM4, dann die 5} END; P:=Table^[i].Init; IF Assigned(P) THEN TProc(P)(); END; except FinalizeUnits; raise; end; end; "C:\Program Files (X86)\Borland\Delphi7\Bin\DCC32.EXE" -$D+ -Y SYSTEM und ohne Debug-Info: "C:\Program Files (X86)\Borland\Delphi7\Bin\DCC32.EXE" -$D- -Y SYSTEM Die geänderte system.pas kommt zurück nach "C:\Program Files (x86)\Borland\Delphi7\Source\Rtl\Sys", die entstandene system.dcu mit Debug-Info nach "C:\Program Files (x86)\Borland\Delphi7\Lib\Debug" und die ohne nach "C:\Program Files (x86)\Borland\Delphi7\Lib". Ggf. muss man zum Kopieren Admin-Rechte haben. Es ist nicht verkehrt, vorher alles zu sichern! Wenn man in system.pas debuggen will, muss man in den Projekt-Optionen bei Compiler die Option [ ] mit Debug-DCUs aktivieren. Das ist wirklich eine harte Nuss gewesen! Bestimmt hätte es auch eine einfachere Lösung gegeben, habe ich aber nicht gefunden. Es ist mir unbegreiflich, warum die FastMM.pas so spät initialisiert wird, obwohl sie oben im *.dpr als erstes stand. Egal - danke für Eure Hilfe. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:56 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz