Hallo nochmal.
Die Sache hat mir keine Ruhe gelassen und deshalb hab ich die vergangenen Tage genauer untersucht, was da eigentlich passiert. Ich liebe nicht zuverlässig reproduzierbare Fehler ...
Nach einiger Zeit des Debugging hab ich die Funktion
_8ByteAlign
als Problemverursacher ausgemacht. Diese gibt bei bestimmten Eingabedaten einen um 8 Byte höheren Wert zurück als sie sollte. Die Folge ist, dass die while-Schleife vorzeitig verlassen wird - es werden deshalb nicht alle Signaturen gefunden.
Basierend auf dem Debugging des Produktivcodes hab ich ein kleines Testprogramm erstellt, das die Problematik verdeutlicht. Die hier benutzten Adressen und Offsets sind von den Debug-Sessions übernommen.
Delphi-Quellcode:
program Project1;
{$APPTYPE CONSOLE}
uses
sysutils,
Windows;
function _8ByteAlign(const offset, base: DWORD): DWORD;
begin
WriteLn((base + offset + 7));
WriteLn((base + offset + 7) AND $FFFFFFF8);
WriteLn(((base + 7) AND $FFFFFFF8));
Result:= ((offset + base + 7) AND $FFFFFFF8) - (base AND $FFFFFFF8);
end;
var
base, offset: DWORD;
i: integer;
begin
for i:= 0 to 8 do begin
base:= $431E814 + i;
offset:= 9293;
WriteLn;
WriteLn(i);
WriteLn(Format('Base: 0x%.8x (%u), Offset: %d', [base, base, offset]));
WriteLn(_8ByteAlign(offset, base));
end;
ReadLn;
end.
Ausgabe:
Code:
0
Base: 0x0431E814 (70379540), Offset: 9293
70388840
70388840
70379536
9304
1
Base: 0x0431E815 (70379541), Offset: 9293
70388841
70388840
70379536
9304
2
Base: 0x0431E816 (70379542), Offset: 9293
70388842
70388840
70379536
9304
3
Base: 0x0431E817 (70379543), Offset: 9293
70388843
70388840
70379536
9304
4
Base: 0x0431E818 (70379544), Offset: 9293
70388844
70388840
70379544
9296
5
Base: 0x0431E819 (70379545), Offset: 9293
70388845
70388840
70379544
9296
6
Base: 0x0431E81A (70379546), Offset: 9293
70388846
70388840
70379544
9296
7
Base: 0x0431E81B (70379547), Offset: 9293
70388847
70388840
70379544
9296
8
Base: 0x0431E81C (70379548), Offset: 9293
70388848
70388848
70379544
9304
Das nächstgrößere Vielfache von 8 ist 9296, nicht 9304. Mit anderen Adressen und Offsets ist die Rückgabe der Funktion unter Umständen nicht so häufig falsch. Eindeutiges Anzeichen für unzuverlässigen Code.
Nach dieser Entdeckung hab ich mich gefragt, was eigentlich die Basisadresse in der Funktion verloren hat, wozu die dienen soll. Es fiel mir keine sinnvolle Antwort ein. Ich habe die Vermutung, dass die Funktion bzw. das Makro im C++ ursprünglich die absolute Adresse berechnet hat.
Hat jemand eine (andere) Idee, wozu die Basisadresse dienen könnte?
Sobald ich die Funktion wie folgt ändere, funktioniert der Code überall zuverlässig, egal mit welchem Delphi-Speichermanager.
Delphi-Quellcode:
function _8ByteAlign(const offset: DWORD): DWORD;
begin
Result:= (offset + 7) AND $FFFFFFF8;
end;
Die entsprechende Änderung hab ich auch im C++-Code gemacht und getestet und das Ergebnis ist wie vorher (Code funktioniert).
Fazit: Viel Detektivarbeit wegen weniger kleiner Fehler. Aber immerhin bin ich nun ziemlich sicher, dass der Code jetzt zuverlässig und (hoffentlich) auch stabil ist
.
Grüße
Dalai