Hallo,
ich habe zur Zeit ein recht nerviges Problem, welches ich euch hier mal kurz schildern möchte.
Ich habe ein Programm, welches im OnShow-Event des Hauptformulars alle Werte verschiedener
XML-Dateien laden soll. Das funktioniert manchmal wunderbar, manchmal kommen aber auch an ständig anderen Stellen verschiedene Fehler.
Beispiele für Fehler:
- 'M' ist kein gültiger Gleitkommawert - obwohl unter dem angefordertem Knoten eine 0 steht. Die Knoten, bei denen dieser Fehler auftritt sind absolut zufällig genauso wie der Buchstabe
- Access violation: read of adress 0xfffffffc - hier bleibt er in der GETMEM.INC bei Zeile 1904 hängen (jedesmal an der selben Stelle).:
Delphi-Quellcode:
{Get the new first free block}
and ecx, [eax - 4]
- Access violation: read of address 0x00000002 - hier bleibt er in der System-Unit in folgender Funktion hängen:
Delphi-Quellcode:
class function TMonitor.GetFieldAddress(const AObject: TObject): PPMonitor;
begin
Result := PPMonitor(PByte(AObject) + AObject.InstanceSize - hfFieldSize + hfMonitorOffset);
end;
Das sind zumindest mal die drei häufigsten Fehler. Wahrscheinlich kann man jetzt noch gar nicht helfen. Leider ist es mir nicht möglich/gestattet hier den kompletten Code zu posten. Dennoch hier der grobe Ablauf
Delphi-Quellcode:
procedure LoadObjects;
var
threadID: DWord;
begin
CreateThread(nil, 0, TFNThreadStartRoutine(@LoadObjectsThreadFunc), nil, 0, threadId);
end;
Delphi-Quellcode:
procedure LoadObjectsThreadFunc(p: pointer);
var
si: TObjectUseType;
sl: TStringList;
err: string;
begin
CoInitialize(nil);
WaitForSingleObject(g_LoadObjectsMutex, INFINITE); //CreateMutex wurde vorher aufgerufen
sl := TStringList.Create;
for si := Low(TObjectUseType) to High(TObjectUseType) do
begin
g_dataManager.getFiles(sl, ObjectFileType[si]);
g_Objects[si].loadFromXMLFiles(sl,err); //DANACH FEHLER
g_Objects[si].Sort(g_SortType);
end;
FreeAndNil(sl);
ReleaseMutex(g_LoadObjectsMutex);
end;
Delphi-Quellcode:
function TPersistentObjectList.LoadFromXMLFiles(const sl: TStringList; var err: string): boolean;
var
FXMLDoc: TXMLDocument;
FSaver: TXMLSaverBase;
i: integer;
FValue: TPersistent_;
FNode: IXMLNode;
begin
err := '';
Result := true;
Clear;
try
try
FSaver := TXMLSaverBase.Create;
if assigned(sl) then
begin
for i := 0 to sl.Count-1 do
begin
FXMLDoc := TXMLDocument.Create(Application);
FXMLDoc.FileName := sl.Strings[i];
FXMLDoc.Active := true;
FNode := FXMLDoc.DocumentElement;
FSaver.Node := FNode;
FValue := TPersistent_Class(GetClass(FSaver.GetStrAttribute(CXML_CLASSNAME,'',true))).Create;
Result := FValue.loadFromXMLNode(FNode,err); //Fehler
FValue.FileName := sl.Strings[i];
Add(FValue);
FreeAndNil(FXMLDoc);
end;
end
else
Result := false;
finally
FreeAndNil(FSaver);
end;
except
Result := false;
end;
end;
Delphi-Quellcode:
function TObjectXYZ.loadFromXMLNode(iNode: IXMLNode;
var err:
string): boolean;
var
FSaver: TXMLSaverBase;
FNode: IXMLNode;
begin
Result := true;
inherited loadFromXMLNode(iNode,err);
try
try
FSaver := TXMLSaverBase.Create;
FSaver.Node := iNode;
FIrgendwas := FSaver.GetDoubleAttribute(CXML_Irgendwas,0,true);
//manchmal bleibt er hier stehen
FWasAnderes := FSaver.GetBoolAttribute(CXML_WasAnderes,false,true);
//manchmal auch hier
{...}
finally
FreeAndNil(FSaver);
end;
except
on E:
Exception do
begin
err := E.
Message;
Result := false;
end;
end;
end;
Delphi-Quellcode:
function TXMLSaverBase.GetDoubleAttribute(const AttributeName: string; DefaultValue: Double; SendException: boolean): Double;
begin
Result := StrToFloat_(GetAttribute(AttributeName, FloatToStr_(DefaultValue), SendException));
end;
Delphi-Quellcode:
function TXMLSaverBase.GetAttribute(const AttributeName: string; DefaultValue: OleVariant; SendException: boolean): OleVariant;
function DoDefault(SendException: boolean): OleVariant;
begin
if SendException then
raise EXMLReadException.Create(' GetAttribute: Node: ' + FNode.NodeName)
else
Result := DefaultValue;
end;
begin
FLastReadError := emptystr;
Result := 0;
try
if Assigned(FNode) then
begin
if(HasAttribute(AttributeName)) then
Result := FNode.Attributes[AttributeName]
else
Result := DoDefault(SendException);
end
else
begin
Result := DoDefault(SendException);
end;
except
Result := DoDefault(SendException);
end;
end;
Der Call-Stack sieht auch jedes mal etwas anders aus. Es hängt auch irgendwie damit zusammen, wann ich die
XML-Dateien lade. Wenn ich sie z.B. beim Klick auf einen Button lade treten noch ganz andere Fehler auf. Zum Beispiel "zu wenig Arbeitsspeicher" (sind 8GB vorhanden und nie ansatzweise voll).
Ich kann mir vorstellen, dass man da wohl nur schwer von außen helfen kann aber vllt hat ja doch jemand eine Idee. Vllt auch ein paar Tipps, wie ich vorgehen kann, um den Fehler einzugrenzen. Hintergrund: Ich muss ein großes Delphi-Projekt von Delphi 7 auf XE5 umstellen und verwende dabei einige Units (wie z.B. XMLSaverBase) des alten Projektes um einigermaßen kompatibel zu bleiben. Die Fehler treten ja wie gesagt auch nur bei jedem 7ten Start oder so auf.
Vielen Dank für eure Mühe.
Grüße
Headbucket