![]() |
Speicherzugriffsverletzung bei Parameterübergabe aus DLL!
Hallo,
ich habe für ein Projekt von mir einige Funktionen zwecks einfacherer Updates in eine Dll ausgelagert! Prinzipiell kenne ich mich mit DLLs aus und bis auf eine Funktion läuft auch alles, wie gewollt! Heir die Prozedur, die mir Probleme macht:
Delphi-Quellcode:
Ich checke abhängig von gewissen Parameter (als Array übergeben) ob die dazugehörigen Dateien vorhanden sind oder nicht! Insgesamt sammele ich alle Informationen in einem String (List), den ich dann als PChar in AResultStr kopiere!
procedure checkFiles(DirP :PChar; GShortP : Array of PChar;var AResultStr : Pchar);stdcall;
var Dir, List, GameMiss :String; GShort : Array of String; MissingShort : Array of String; i,a,b,GNum : Integer; evenAdded, MainMiss : boolean; begin MainMiss := FALSE; Dir := String(DirP); setlength(GShort,length(GShortP)); For i := 0 to length(GShortP)-1 do GShort[i] := String(GShortP[i]); For i := 0 to length(GShort)-1 do begin GNum := 1; If GShort[i] ='Short1' then begin If not FileExists(Dir+'Datei1') then begin setlength(MissinGShort,length(MissinGShort)+1); MissinGShort[length(MissinGShort)-1] := 'Datei1'; GameMiss := 'True'; end else begin GameMiss := 'False'; end; end; If GShort[i] ='short2' then begin If not FileExists(Dir+'Datei2') then begin setlength(MissinGShort,length(MissinGShort)+1); MissinGShort[length(MissinGShort)-1] := 'Datei2'; GameMiss := 'True'; end else begin GameMiss := 'False'; end; end; If GShort[i] ='Short3' then begin If not FileExists(Dir+'Datei3') then begin setlength(MissinGShort,length(MissinGShort)+1); MissinGShort[length(MissinGShort)-1] := 'Datei3'; GameMiss := 'True'; end else begin GameMiss := 'False'; end; If not FileExists(Dir+'Datei4') then begin setlength(MissinGShort,length(MissinGShort)+1); MissinGShort[length(MissinGShort)-1] := 'Datei4'; GameMiss := 'True'; end else begin If GameMiss <> 'True'then GameMiss := 'False'; end; end; . . //Und . //so . //weiter . If not FileExists(Dir+'Datei5') then begin For b := 0 to length(MissinGShort)-1 do If MissinGshort[b] = 'Datei5' then evenadded := true; if not evenadded then begin setlength(MissinGShort,length(MissinGShort)+1); MissinGShort[length(MissinGShort)-1] := 'Datei5'; end; MainMiss := True; end; If GameMiss <> '' then If (GameMiss = 'False') and (not MainMiss) then If i = 0 then List := GShort[i]+'*T*' + IntToStr(Gnum) + Chr(13) else List := List + GShort[i]+'*T*' + IntToStr(Gnum) + Chr(13) else if (GameMiss = 'True') or (MainMiss) then If i = 0 then List := GShort[i]+'*F*' + IntToStr(Gnum) + Chr(13) else List := List + GShort[i]+'*F*' + IntToStr(Gnum) + Chr(13) ; GameMiss := ''; MainMiss := False; end; For i := 0 to length(GShort)-1 do begin GNum := 2; If GShort[i] ='Short4' then begin If not FileExists(Dir+'Datei6') then begin setlength(MissinGShort,length(MissinGShort)+1); MissinGShort[length(MissinGShort)-1] := 'datei6'; GameMiss := 'True'; end else begin GameMiss := 'False'; end; . . //Und . //so . //weiter . If not FileExists(GCFDir+'Source Dedicated Server.gcf') then begin For b := 0 to length(MissinGShort)-1 do If MissinGshort[b] = 'Source Dedicated Server.gcf' then evenadded := true; if not evenadded then begin setlength(MissinGShort,length(MissinGShort)+1); MissinGShort[length(MissinGShort)-1] := 'Source Dedicated Server.gcf'; end; MainMiss := True; end; If GameMiss <> '' then If (GameMiss = 'False') and (not MainMiss) then If List ='' then List := GShort[i]+'*T*' + IntToStr(Gnum) + Chr(13) else List := List + GShort[i]+'*T*' + IntToStr(Gnum) + Chr(13) else if (GameMiss = 'True') or (MainMiss) then If List ='' then List := GShort[i]+'*F*' + IntToStr(Gnum) + Chr(13) else List := List + GShort[i]+'*F*' + IntToStr(Gnum) + Chr(13) ; GameMiss := ''; MainMiss := False; end; For a:=0 to length(MissinGShort)-1 do List := List + Chr(13) + '\' + MissinGShort[a]; //i := length(List); <--------Wenn ich mir zum debuggen diese Zeilen auskommentiere, //messagedlg(IntToStr(i),mtWarning ,mbYesNoCancel ,1); <--------Und mir z.B. die Länge von List ausgeben lass, bekomme //messagedlg(List,mtWarning ,mbYesNoCancel ,1); <--------ich später keine Zugriffsverletzung mehr! AResultStr := nil; AResultStr := PChar(List); end; Ich habe versucht AResultStr zum einen als Rückgabewert einer Funktion zu übergeben:
Delphi-Quellcode:
Oder eben wie oben als Var-Parameter!
function checkFiles(DirP :PChar; GShortP : Array of PChar): Pchar;stdcall;
. . . AResultStr := PChar(List); result := AResultStr; Beides mal bekomme ich eine Speicherzugriffsverletzung! Aber ich komme nicht auf den Grund des Problems, weil: 1. Wenn ich mir zur Laufzeit in Delphi die Variable List anschaue, ist alles ok! Sieht so aus:
Delphi-Quellcode:
Doch beim übergeben an AResultStr mit:
List := 'datei1*T*1'#$D'datei2*T*1'#$D'datei3*T*1'......
Delphi-Quellcode:
bleibt AResultStr unbestimmt!
AResultStr := PChar(List);
Und ich bekomme die Zugriffsverletzung beim nächsten Schritt! 2. Wenn ich mir zur Laufzeit, z.B die Läbge von List als MessageDlg anzeigen lass funktioniert später die übergabe von List auf AResultStr ohne Probleme und ich bekomme keine Speicherzugriffsverletzung! 3. Wenn ich die gleiche Procedure nehme, Alles weglasse und nur einen String von Hand eingebe und an AResulStr übergeben lasse funktioniert auch alles! Beispiel:
Delphi-Quellcode:
Danke, dass ihr bis hier durchgehalten habt!
procedure checkFiless(GCFDirP :PChar; GShortP : Array of PChar;var AResultStr : Pchar);stdcall;
var Astr :String; begin Astr := 'Short1*T*1' + Chr(13) + 'Short1*T*1' + Chr(13) +'Short1*T*1' + Chr(13) +'Short1*T*1' + Chr(13) +'Short1*T*1' + Chr(13) +'Short1*T*1' + Chr(13) + '\' + 'Datei1' + Chr(13) + '\' + 'Datei1'+ Chr(13) + '\' + 'Datei1'; AResultStr := Pchar(Astr); end; Sillium |
Re: Speicherzugriffsverletzung bei Parameterübergabe aus DLL
Wie sieht die USES-Liste der DLL aus?
|
Re: Speicherzugriffsverletzung bei Parameterübergabe aus DLL
nach dem aus deiner Funktion zurück gekehrt wurde ist "List" nicht mehr definiert sondern freigegeben. Das heißt dein Pointer auf "List" (also dein Result) zeigt auf eine Stelle im Speicher die nicht mehr da ist.
|
Re: Speicherzugriffsverletzung bei Parameterübergabe aus DLL
Das vermute ich auch. Wenn er allerding den Delphi-MM benutzen würde, dann könnte er direkt Strings benutzen (deswegen die Frage nach der USES-Liste). Ist allerdings auch ein gewisser Overhead ;)
Am besten ist es, wenn Aufrufer und Aufgerufener eine gemeinsame Funktion zum Allozieren und Deallizieren des Speichers haben ;) ... dann kann der eine einen Pointer des anderen freigeben. |
Re: Speicherzugriffsverletzung bei Parameterübergabe aus DLL
Jupp
Das AResultStr := nil; vor AResultStr := PChar(List); kannst'e erstmal weglassen ist "unnötiger" Code. So könnte man dafür sorgen, das List nicht freigegeben wird. Wie oben schon gesagt wurde, werden lockale Variablen am Ende der Prozedur freigeben (das Gilt zwar nicht für Objekte/Pointer..., wo nur de Zeiger "gelöscht" wird, aber bei Strings und dynamischen Arrays wird auch der Inhalt mit freigegeben.
Delphi-Quellcode:
Aber dann musß du dann später den String an der Stelle natürlich auch selber freigeben ;)
AResultStr := PChar(List);
Pointer(AResultStr) := nil; // ändert nur den Pointer auf den String und läßt den Inhalt reserviert [add] DelphiMM :shock: der DelphiMM shared den Speicher nicht und da dann in jedem Modul ein eigener MM aktiv ist, kann man die Strings "nicht" in ein anders Modul übergeben, jedenfalls wenn dort dann der Sringinhalt geändert wird, wozu in vielen Fällen auch nur das ändern des Referenzzählers zählt... |
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:33 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz