AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

FastMM4 und Delphi 7

Ein Thema von Bernd1982 · begonnen am 1. Jan 2018 · letzter Beitrag vom 2. Jan 2018
Antwort Antwort
Bernd1982

Registriert seit: 22. Dez 2009
11 Beiträge
 
#1

FastMM4 und Delphi 7

  Alt 1. Jan 2018, 22:32
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!
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.068 Beiträge
 
Delphi 12 Athens
 
#2

AW: FastMM4 und Delphi 7

  Alt 2. Jan 2018, 00:46
Ich hab grade nur 'nen FastMM4 von 2007 hier rumliegen, aber da wird sich wohl nicht viel geändert haben.
Zitat von FstMM4.pas:
Delphi-Quellcode:
{Checks that no other memory manager has been installed after the RTL MM and
that there are currently no live pointers allocated through the RTL MM.}

function CheckCanInstallMemoryManager: boolean;
begin
  {Default to error}
  Result := False;
  {Is FastMM already installed?}
  if FastMMIsInstalled then
  begin
{$ifdef UseOutputDebugString}
    OutputDebugString(AlreadyInstalledMsg);
{$endif}
{$ifndef NoMessageBoxes}
    AppendStringToModuleName(AlreadyInstalledTitle, LErrorMessageTitle);
    ShowMessageBox(AlreadyInstalledMsg, LErrorMessageTitle);
{$endif}
    exit;
  end;
  ...
  usw.
  ...
end;


initialization
{$ifndef BCB}
  {Initialize all the lookup tables, etc. for the memory manager}
  InitializeMemoryManager;
  {Has another MM been set, or has the Borland MM been used? If so, this file
   is not the first unit in the uses clause of the project's .dpr file.}

  if CheckCanInstallMemoryManager then
  begin
  {$ifdef ClearLogFileOnStartup}
    DeleteEventLog;
  {$endif}
    InstallMemoryManager;
  end;
Wenn etwas Anderes vorher Speicher mit DelphiMM reserviert hatte oder sonst irgendwas passt nicht, dann installiert sich FastMM nicht und gibt dafür eine Fehlermeldung aus.

Aktiviere mal UseOutputDebugString, starte dein Programm im Debugger und schau was im Log passiert.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Bernd1982

Registriert seit: 22. Dez 2009
11 Beiträge
 
#3

AW: FastMM4 und Delphi 7

  Alt 2. Jan 2018, 01:15
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
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.068 Beiträge
 
Delphi 12 Athens
 
#4

AW: FastMM4 und Delphi 7

  Alt 2. Jan 2018, 01:20
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.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu ( 2. Jan 2018 um 01:25 Uhr)
  Mit Zitat antworten Zitat
Bernd1982

Registriert seit: 22. Dez 2009
11 Beiträge
 
#5

AW: FastMM4 und Delphi 7

  Alt 2. Jan 2018, 01:25
Genau so sollte es sein. Isses aber leider nicht 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?
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.068 Beiträge
 
Delphi 12 Athens
 
#6

AW: FastMM4 und Delphi 7

  Alt 2. Jan 2018, 01:32
Aktivieren: in der Options-INC des FastMM

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)
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Bernd1982

Registriert seit: 22. Dez 2009
11 Beiträge
 
#7

AW: FastMM4 und Delphi 7

  Alt 2. Jan 2018, 01:49
Danke. Hab' das {$define UseOutputDebugString} aktiviert. Hilft aber auch nix, der FastMM4 wird ja gar nicht erst lebendig

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!
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#8

AW: FastMM4 und Delphi 7

  Alt 2. Jan 2018, 06:26
Warum da noch selbst mit den Directiven rumspielen verwende doch einfach FastMM4Options
http://jedqc.blogspot.de/2007/07/new...interface.html

gruss
  Mit Zitat antworten Zitat
Bernd1982

Registriert seit: 22. Dez 2009
11 Beiträge
 
#9

AW: FastMM4 und Delphi 7

  Alt 2. Jan 2018, 17:26
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

Ich habe nämlich 2 Änderungen gemacht:
  1. Ich habe die INITILAIZATION in FastMM4.pas mit ASM NOP NOP NOP NOP END; als Kennung anfangen lassen.
  2. Ich habe die system.pas geändert und neu kompiliert. Bei InitUnits wird jetzt zuerst die FastMM4 gesucht und früher initialisiert als vom Compiler vorgegeben.

Zu 1.: Die FastMM4.pas sieht am Ende jetzt also so aus:
Delphi-Quellcode:
initialization
  asm
  NOP
  NOP
  NOP
  NOP
  end;
  RunInitializationCode;
finalization
{$ifndef PatchBCBTerminate}
  FinalizeMemoryManager;
{$endif}
end.
Die 4 NOPs ergeben 4 x $90 also ein DWORD $90909090 im Code. Daran kann man diese Unit in der Liste erkennen.

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:
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;
Die system.pas muss man manuell im CMD-Fenster mit dem Kommandozeilencompiler DCC32 kompilieren:

"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.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:45 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz