Einzelnen Beitrag anzeigen

BerndS

Registriert seit: 8. Mär 2006
Ort: Jüterbog
492 Beiträge
 
Delphi 12 Athens
 
#1

raise innerhalb einer DLL setzt GetLastError auf 0

  Alt 7. Jan 2016, 14:02
Delphi-Version: XE7
Hallo, mir ist gerade aufgefallen, dass ein Programmteile der vorher in einer EXE waren und nun in eine DLL ausgelagert wurde sich leider ganz anders verhält. Hintergrund ist, dass das Hauptprogramm als DLL ausgeliefert werden soll um bestimmte Funktionen per Export für andere Programme Verfügung zu stellen da ein Export in als Exe nicht funktionierte.

Hier ein Beispiel:
Delphi-Quellcode:
try
    with TFileStream.Create('C:\test.dat', fmOpenRead) do
      Free;
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message, ' LastError=', GetLastError);
  end;
In der Exe ist im except GetLastError=2 aber in der DLL wird GetLastError auf 0 gesetzt sobald raise in TFileStream.Create aufgerufen wird.

Ich habe die Sache schon im Debuger untersucht und auch die Stelle gefunden, wo das passiert.
Raise ruft intern _RaiseExcept (System.pas) auf die dann per CALL RaiseList in die Unit Sysinit springt.
Delphi-Quellcode:
asm
        MOV CL,ModuleIsLib
        MOV EAX,TlsIndex
        TEST CL,CL
        JNE @@isDll
        ...
        RET
        ...
@@isDll:
        PUSH EAX
        CALL TlsGetValue
        TEST EAX,EAX
        JE @@initTls
end;
Da CL = 1 wird nach @@isDll gesprungen und in TlsGetValue GetLastError auf 0 gesetzt.
Ich habe die Quellen von Delphi2007 und von XE7 verglichen. Es ist in beiden Versionen identisch.
Es hat zur Folge, dass alle Programmteile einer DLL die im except eine Fehlerbehandlung mit GetLastError durchführen nicht mehr funktionieren.

Meine Frage ist nun:
1. kann man das irgendwie beheben, ohne die eigenen Quellen zu ändern?
2. Ist das in der aktuellen Version von Delphi immer noch so?

Gruß Bernd
  Mit Zitat antworten Zitat