PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [Delphi] TIniFile und EAccessViolation



MagicMagor
16.06.2004, 23:36
Diesmal habe ich, denke ich, wirklich ein Problem, auf das ich mir keinen Reim machen kann.

Ich habe ein dynamisches Array "VolkDaten" dessen Inhalt ich in ein IniFile schreiben will. Das Array wird vorher dimensioniert und auch gefüllt.
Hier mal der Code der Funktion zum Schreiben in das IniFile:



procedure TPeople.ResetIniDataVolk;
var Ini: TIniFile;
i: integer;
Datei: Textfile;
b: TGroupBuilding;
u: TGroupUnit;
Test:string;
begin
ResetVolkData;
AssignFile(Datei, GamePath+'daten\volk.ini');
try
ReWrite(datei);
CloseFile(datei);
// Ini-Datei beschreiben:
Ini:=TIniFile.Create(GamePath+'daten\volk.ini');
Ini.WriteInteger('Allgemein', 'Anzahl', 4);
for i:=0 to 3 do
begin
with VolkDaten[i] do
begin
Ini.WriteString('Allgemein', 'Volk'+InttoStr(i), Name);
for b:=Farm to Military do
Ini.WriteInteger(Name, 'BuildingHP'+TGrBuildtoStr(b), BuildingHP[b]);
for u:=Regular to Artilery do
begin
Ini.WriteInteger(FVolkDaten[i].Name, 'UnitHP'+TGrUtoStr(u), FVolkDaten[i].UnitHP[u]);
Ini.WriteInteger(FVolkDaten[i].Name, 'UnitAttack'+TGrUtoStr(u), FVolkDaten[i].UnitAttack[u]);
Ini.WriteInteger(FVolkDaten[i].Name , 'UnitDefense'+TGrUtoStr(u), FVolkDaten[i].UnitDefense[u]);
end;
end;
end;
finally
Ini.Free;
end;
end;

An der fett markierten Zeile bricht das Programm dann mit einer EAccessViolation ab. Das interessante und für mich seltsame, an der Geschichte ist, daß ich vorher eine Funktion hatte, die das Array korrekt in ein IniFile geschrieben hat. Die einzigen Änderung die ich vorgenommen habe um zu obiger Prozedur zu kommen waren:
- Das Array als Property der Klasse TPeople eingeführt und die Prozedur zu einer Methode selbiger Klasse gemacht.
- Einige Schleifen eingeführt
Wenn ich obigen Code als eigenständige Prozedur aufrufe und Volkdaten[i] über das Objekt People aufrufe, kommt derselbe Fehler. Selbst wenn ich Name oder BuildingHP(b) durch konstante Werte ersetze kommt der Fehler, ebenso wenn ich die Schleife entferne und b durch einen festen Wert ersetze.
Die ersten beiden WriteBefehle werden ausgeführt, allerdings taucht der Wert von
Ini.WriteString('Allgemein', 'Volk'+InttoStr(i), Name); Nicht im IniFile auf.. wenn ich Name durch einen konstanten String ersetze allerdings schon. Aber wie gesagt, wenn ich in der abbrechende Zeile gar nicht mehr auf VolkDaten[i] zugreife taucht der Fehler trotzdem auf.
Ich hab ehrlich gesagt keine Ideen mehr wo der Fehler seine Ursache haben könnte, geschweige denn wie er zu beheben ist.
Falls ihr noch weitere Codeschnipsel braucht, einfach sagen.
ResetVolkData funktioniert übrigens tadellos.

Ineluki
17.06.2004, 19:54
Was sind denn das fuer Datentypen ?
b: TGroupBuilding;
u: TGroupUnit;

MagicMagor
17.06.2004, 20:24
Selbst erstellte Aufzählungstypen.
Edit:

TGroupBuilding = (Farm, Mine, Production, House, Special, Military);
TGroupUnit = (Regular, Horse, Shoot, Mage, Artilery);
Edit2:
Der Fehler lag anscheindend doch in der Procedure ResetVolkData.
Damit der Thread hier nicht total sinnlos ist, frag ich einfach mal wieso ich innerhalb von ResetVolkData nicht auf die Eigenschaft VolkDaten zurückgreifen sondern auf das Feld FVolkDaten zurückgreifen muss (seit der Änderung wird das IniFile auch korrekt beschrieben).
Hier mal die Typdeklaration von TPeople:

TPeople = class
private
FProgramPath: string;
FVolkDaten: array of TVolkDaten;
procedure SetVolkDaten(idx: integer; value: TVolkDaten);
function GetVolkDaten(idx:integer):TVolkDaten;
public
constructor Create;
procedure ResetIniDataVolk;
procedure GetIniDataVolk;
procedure ResetIniData;
procedure ResetVolkData;
property GamePath: string read FProgramPath write FProgramPath;
property VolkDaten[idx:integer]: TVolkDaten read GetVolkDaten write SetVolkDaten;
end;
.
.
.

procedure TPeople.SetVolkDaten(idx: integer; value: TVolkDaten);
begin
FVolkDaten[idx]:=value;
end;


In ResetVolkData habe ich FVolkDaten dimensioniert und dann mit

with VolkDaten[0] do
Das ganze gefüllt. Als ich da das VolkDaten in FVolkDaten geändert habem hat sich der Fehler behoben. Wäre über ein wenig Aufklärung in Bezug darauf dankbar.. eigentlich habe ich gedacht ich hätte die Properties verstanden, aber das scheint nicht wirklich der Fall zu sein. =)

Ineluki
18.06.2004, 00:26
Wieso solltest du denn in SetVolkDaten auf Volkdaten zugreifen wollen und nicht auf FVolkDaten ?

Properties sind wenn man so will pseudovariblen. Fuer das lesen wird die Read-Funktion aufgerufen und fuer das Schreiben die Write-Funktion. Wenn du nun in der Funktion zum Schreiben in das Property wieder auf das Property zugreifst hast du doch sowas wie eine Endlosschlife, oder er macht dir irgend welchen undefinierten mist.

Zudem sind zugriffe ueber properties in der regel wesentlich langsamer als auf variablen, da ja erst sprungaddressen etc generiert werden muessen usw usw ... Innerhalb des Objectes also nach moeglichkeit immer ueber das Member (also das F*) gehen und properties AUSSCHLIESSLICH als schnittstellen verwenden zum setzen von bestimmen eigenschaften, nicht zum exzessiven datenverkehr

Falls ich jetzt was falsch verstanden haben sollte, und du was anderes machen wolltest, klaer mich bitte auf ^__^

btw .. ich selber hab noch nie aufzaehlungen in Pascal verwendet ^__^