AGB  ·  Datenschutz  ·  Impressum  







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

ShareMem ohne ShareMem.dll und Co.

Ein Thema von himitsu · begonnen am 13. Jun 2009 · letzter Beitrag vom 15. Okt 2009
Antwort Antwort
Benutzerbild von himitsu
himitsu
Online

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

ShareMem ohne ShareMem.dll und Co.

  Alt 13. Jun 2009, 16:36
Hier habt ihr noch ein kleines "Abfallprodukt" meines Hier im Forum suchenhimXML

Es schleift praktisch jeden Speichermanager von einer Delphi-EXE in eine Delphi-DLL durch.

Dabei ist es egal, ob nun der Standard-SpeicherManager verwendet wird oder ein Anderer.

Und es wird auch keine zusätzliche Datei benötigt, wie es bei Delphi-Referenz durchsuchenShareMem der Fall ist.


Systemvorausstzung:
die DLL (bzw. die himiSM.pas) benötigt mindestens ein Delphi, wo TMemoryManagerEx verfügbar ist
und die EXE sollte vermutlich mindestens mit Delphi 4 erstellt werden.


Diese Unit muß in die DLL aufgenommen werden:
> erster Uses-Eintrag in deren .DPR
Delphi-Quellcode:
Unit himiSM_DLLInit;

Interface

Implementation
  {$WARN SYMBOL_DEPRECATED OFF}

  Uses Windows;

  Var Name: Array[0..29] of AnsiChar = 'himiShareMem_xxxxxxxxxxxxxxxx'#0;
    i, i2: Integer;
    Map: THandle;
    View: PAnsiChar;
    MemMgr: TMemoryManager;
    MemMgrEx: TMemoryManagerEx;
    OldMemMgr: TMemoryManagerEx;

Initialization
  GetMemoryManager(OldMemMgr);

  i2 := GetCurrentProcessId;
  For i := 15 downto 0 do Begin
    If Byte(i2 and $0F) <= 9 Then Name[i + 13] := AnsiChar((i2 and $0F) + Ord('0'))
    Else Name[i + 13] := AnsiChar((i2 and $0F) - 10 + Ord('A'));
    i2 := i2 shr 4;
  End;
  Map := OpenFileMappingA(FILE_MAP_READ, False, @Name);
  View := MapViewOfFile(Map, FILE_MAP_READ, 0, 0, 0);
  If (Map <> 0) and Assigned(View) Then
    If Assigned(PPointer(View + 3 * SizeOf(Pointer))^) Then Begin
      CopyMemory(@MemMgrEx, View, SizeOf(MemMgrEx));
      SetMemoryManager(MemMgrEx);
    End Else Begin
      CopyMemory(@MemMgr, View, SizeOf(MemMgr));
      SetMemoryManager(MemMgr);
    End;
  UnmapViewOfFile(View);
  CloseHandle(Map);

Finalization
  SetMemoryManager(OldMemMgr);

End.
Und zum Laden der DLL wird dann "einfach" nur noch statt LoadLibrary das LoadLibrarySM verwendet
Delphi-Quellcode:
Function LoadLibrarySM(LibFileName: PChar): HMODULE;
  Var Name: Array[0..29] of AnsiChar;
    i, i2: Integer;
    Map: THandle;
    View: PAnsiChar;
    MemMgr: {$IF Declared(TMemoryManagerEx)}TMemoryManagerEx{$ELSE}TMemoryManager{$IFEND};
    Error: HRESULT;

  Begin
    Error := ERROR_INVALID_FUNCTION;
    Name := 'himiShareMem_xxxxxxxxxxxxxxxx'#0;
    i2 := GetCurrentProcessId;
    For i := 15 downto 0 do Begin
      If Byte(i2 and $0F) <= 9 Then Name[i + 13] := AnsiChar((i2 and $0F) + Ord('0'))
      Else Name[i + 13] := AnsiChar((i2 and $0F) - 10 + Ord('A'));
      i2 := i2 shr 4;
    End;
    Map := CreateFileMappingA(INVALID_HANDLE_VALUE, nil, FILE_MAP_READ, 0, 6 * SizeOf(Pointer), @Name);
    View := MapViewOfFile(Map, FILE_MAP_READ or FILE_MAP_WRITE, 0, 0, 0);
    _DLL := 0;
    Try
      If (Map <> 0) and Assigned(View) Then Begin
        GetMemoryManager(MemMgr);
        ZeroMemory(View, 6 * SizeOf(Pointer));
        CopyMemory(View, @MemMgr, SizeOf(MemMgr));
        Result := LoadLibrary(LibFileName);
        Error := GetLastError;
      End Else Begin
        Result := 0;
        Error := ERROR_ACCESS_DENIED;
      End;
    Finally
      UnmapViewOfFile(View);
      CloseHandle(Map);
      SetLastError(Error);
    End;
  End;

Info:
Es macht übrigens auch nichts aus, wenn in einem von Beiden (EXE und DLL) keiner der Codes eingebaut ist ... in diesem Falls wird einfach nur keine Umleitung eingerichtet.

Also wenn die DLL mit deim "einfachen" LoadLibrary geladen wird oder die DLL den Code nicht enthält.



Anhang:
himiSM_DLLInit.pas * » * kommt in die DLL
himiSM_LoadLibrary.pas * » * kommt in die EXE (oder eine andere DLL) und enthällt die LoadLibrarySM
Angehängte Dateien
Dateityp: zip himism_205.zip (1,8 KB, 14x aufgerufen)
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Apollonius

Registriert seit: 16. Apr 2007
2.325 Beiträge
 
Turbo Delphi für Win32
 
#2

Re: ShareMem ohne ShareMem.DLL

  Alt 13. Jun 2009, 16:41
Gute Idee!
Nach LoadLibrary könntest du noch GetLastError speichern und am Ende der Funktion wieder setzen (die Funktionen im Finally-Block könnten sonst am Fehlercode herumpfuschen).
Wer erweist der Welt einen Dienst und findet ein gutes Synonym für "Pointer"?
"An interface pointer is a pointer to a pointer. This pointer points to an array of pointers, each of which points to an interface function."
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

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

Re: ShareMem ohne ShareMem.dll und Co.

  Alt 13. Jun 2009, 16:51
Stimmt, hab ich garnicht dran gedacht

(kommt davon, wenn man im eigenem Code eine Exception wirft und es extra hierfür mit als eigenständige Funktion umbaut)


Und schon geändert
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Benutzerbild von igel457
igel457

Registriert seit: 31. Aug 2005
1.622 Beiträge
 
FreePascal / Lazarus
 
#4

Re: ShareMem ohne ShareMem.dll und Co.

  Alt 13. Sep 2009, 23:36
Es geht auch einiges einfacher, auch wenn dann manuell eine Funktion aufgerufen werden muss. Allerdings entstehen so auch keine "wilden" Abhängigkeiten zur Windows-API.

Dll:
Delphi-Quellcode:
var
  old_mgr: TMemoryManagerEx;
  new_mgr: TMemoryManagerEx;
  mem_mgt: Boolean = false;

procedure InitMemMgr(mgr: TMemoryManagerEx);
begin
  if not mem_mgt then
  begin
    mem_mgt := true;
    GetMemoryManager(old_mgr);
    
    new_mgr := mgr;
    SetMemoryManager(new_mgr);
  end;
end;

exports
  InitMemMgr;

initialization

finalization
  if mem_mgt then
    SetMemoryManager(old_mgr);
Host:
Delphi-Quellcode:
type
  TInitMemMgrProc = procedure(mgr: TMemoryManagerEx);

var
  proc: TInitMemMgrProc;
  handle: THandle;
  mgr: TMemoryManagerEx;

[...]
handle := LoadLibrary('foo');
@proc := GetProcAddress(handle, 'InitMemMgr');
if Assigned(proc) then
begin
  GetMemoryManager(mgr);
  proc(mgr);
end;
PS: Ich frage mich ja, warum Borland das mit einer extra DLL gelöst hat... Gibt es da einen Grund? Die DLL-Daten und somit die Pointer auf die Memorymanagement-Funktionen werden bei jedem Laden der DLL doch instanziert und somit an die aufrufende Anwendung angepasst... Gibt es da einen guten Grund?
Andreas
"Sollen sich auch alle schämen, die gedankenlos sich der Wunder der Wissenschaft und Technik bedienen, und nicht mehr davon geistig erfasst haben als die Kuh von der Botanik der Pflanzen, die sie mit Wohlbehagen frisst." - Albert Einstein
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

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

Re: ShareMem ohne ShareMem.dll und Co.

  Alt 14. Sep 2009, 00:43
Du hast da aber ein "kleines" Problem:
Und zwar wenn in der DLL Initialisations-Abschnitte anderer Units existieren.
z.B. wenn die SysUtils oder andere Units in der DLL eingebunden sind, dann würde der Speicher-Manager der DLL schon vor Aufruf deiner Init-Prozedur verwendet und du würdest einfach diesen Manager mit dem anderen überschreiben.
> also es ist im "alten" Manager schon Speicher reserviert, welcher eventuell versucht wird über den "neuen" Manager zu verändern.


Wenn du nun nicht sicherstellen kannst, daß deine Änderung des Speichermanagers korrekt abläuft, dann solltest du vorher wenigstens, z.B. via GetMemoryManagerState (seit FastMM), feststellen, ob die "alte" Speicherverwaltung noch ungenutzt ist und dann entweder nicht diese ersetzen und/oder eine Fehlermeldung ausgeben.



Ach ja, warum Borland es in einer DLL verlagert hat:
- diese DLL wurde statisch geladen
- sie wird also schon vor der EXE geladen
und ebenfalls vor einer anderen DLL, wo sie eingebunden wurde
- sie wird auch als Letztes wieder entladen
- und da diese DLL immer als Erstes geladen und Letzes entladen wird, kann man ihre Speicherverwaltung ohne Probleme für alles Andere verwenden

- ein winziger Nachteil ist, daß man dann alles, was die Speicherverwaltung betrifft, in diese DLL auslagern muß,
welches nun auch eventuell in der EXE verwendete Fehlerüberwachungen anginge ... drum hab ich auch versucht die Verwaltung der EXE in die DLL durchzuschleifen, wärend Borlands ShareMem den Manager der DLL in die EXE einfügt


PS: so wild ist es garnicht ... es wird nur vor dem Start der DLL ein gemeinsamer Speicherbereich besorgt (in diesem Fall eine MMF) und dort der Speichermanager der EXE gespeichert
und der Rest st eine Prüfung, ob auch wirklich ein externer Manager vorhanden ist und nur dann wird er ersetzt und außerdem wurde auf die unterschiedlichen Manager-Verwaltungen eingegangen ... heißt, man kann die DLL genauso mit einer Delphi7-EXE (TMemoryManager) laufen lassen, wie mit z.B. einer EXE von Delphi 2009 (TMemoryManagerEx).
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

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

Re: ShareMem ohne ShareMem.dll und Co.

  Alt 15. Okt 2009, 17:11
Hab 'nen kleinen Fehler behoben (da war noch 'ne alte Variable im Code, welche nicht mehr deklariert war)

Außerdem wurde die Unit himiSM_LoadLibrary so geändert, daß die nun auch in älteren Delphis läuft, welche noch kein TMemoryManagerEx kennen.

Und zusätzlich hab ich noch eine weitere Prozedur eingefügt.

entweder man läßt seine DLL via LoadLibrarySM

oder initialisiert Einiges mit PreLoadSM
- hier kann man dann seine DLL mit LoadLibrary laden
- allerdings bleibt dann der SharingSpeicher erhalten (sind aber nur 24 Byte)


ach ja, es gibt im Anhang auch eine kleine Demo dazu
Angehängte Dateien
Dateityp: 7z himism_846.7z (45,9 KB, 20x aufgerufen)
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  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 12:20 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