![]() |
Wo kommt auf einmal "fpc_shortstr_to_ansistr" her?
Ich sitze hier gemütlich an einem Programmierprojekt für die Schule (ich soll
![]() Zitat:
Ich wundere mich über fpc_shortstr_to_ansistr und überprüfe nochmal, ob überall
Delphi-Quellcode:
eingeschaltet ist. Fehlanzeige, ich habe es nirgendwo vergessen. Umso wunderswerter ist es, dass in der angegebenen Prozedur gar keine Strings benutzt werden. Lediglich zwei andere Prozeduren, die von genannter aufgerufen werden (RunMatch und TestRun) weisen an zwei Stellen welche zu (aber müsste die Adresse nicht auch im Stacktrace auftauchen?). Und zwar von AnsiString zu AnsiString, Shortstrings sind nirgendwo im Spiel.
{$longstrings on}
Nach ein bisschen weiterem erfolglosen Rumprobieren habe ich dann mal in den Assemblercode geschaut. Und tatsächlich, an zwei Stellen (in RunMatch und TestRun jeweils eine) fand sich folgendes:
Code:
Davor ein FPC_ANSISTR_DECR_REF@PLT und danach ein FPC_ANSISTR_INCR_REF@PLT und ein FPC_ANSISTR_DECR_REF@PLT.
call fpc_shortstr_to_ansistr@PLT
Wo kann das herkommen? Ich zerbreche mir daran jetzt schon 1,5 Stunden den Kopf und finde den Punkt nicht :lol: Das ganze tritt sowohl unter 2.4.2 als auch unter 2.4.4 auf. Ich habe es leider nicht geschafft, das Problem mit einer minimalistischen Demo zu reproduzieren, aber bei Interesse kann ich auch den kompletten Programmcode rausrücken, ich wollte es später sowieso unter der AGPL veröffentlichen. Mir fällt kein Grund ein, wo das herkommen kann. Bug im FPC? Vielleicht, aber unwahrscheinlich, in 99% der Fälle liegt der Fehler bei einem selber :stupid: Aber mir gehen einfach die Ideen aus. Wenn irgendjemandem irgendeine Erklärung einfällt, immer her damit, egal wie unrealistisch sie auch sein mag. Sonst weiß ich nicht mehr weiter :cry: |
AW: Wo kommt auf einmal "fpc_shortstr_to_ansistr" her?
Ich habe nun zwar null Ahnung von FPC, aber wenn du diesen Diagnosevorgang deinem Infolehrer einfach mal präsentierst, wird der doch 100%ig aus Scham direkt erstmal kündigen :mrgreen: ... und vorher eine 1+ verteilen.
|
AW: Wo kommt auf einmal "fpc_shortstr_to_ansistr" her?
Zitat:
[ADD] Mittlerweile hab ich fpc_shortstr_to_ansistr wegbekommen, indem ich
Delphi-Quellcode:
durch
string
Delphi-Quellcode:
ersetzt habe. Dafür tritt die AV jetzt in FPC_ANSISTR_INCR_REF auf :cry:
AnsiString
|
AW: Wo kommt auf einmal "fpc_shortstr_to_ansistr" her?
Kleiner Tipp zu Beginn: Wenn du mit "-gl" kompilierst, dann sollte(!) dir der Compiler gleich die Zeilennummer und die Datei beim Backtrace mitanzeigen, dann musst du nicht von Hand rumsuchen.
Kannst du mal bitte den Code der RunGeneration zeigen und vielleicht auch markieren wo sich in etwa der Aufruf zu fpc_shortstr_to_ansistr befinden soll? Alternativ kannst du auch einfach den entsprechenden Assemblerteil der Prozedur zeigen. Wo hast du denn {$longstrings on} gesetzt? Vor einem eventuellen {$mode delphi/objfpc} oder danach? Wenn davor, dann setze das mal überall dahinter hin. Ansonsten kannst du auch einfach mal Free Pascal 2.6.0 ausprobieren, auch wenn ich nicht denke, dass sich da viel geändert hat (allerdings habe ich auch nicht jeden Bugfix im Kopf). Gruß, Sven |
AW: Wo kommt auf einmal "fpc_shortstr_to_ansistr" her?
Zitat:
Zitat:
Delphi-Quellcode:
Nach im nachhinein nicht mehr nachvollziehbarem Rumgewurschtel, ist fpc_shortstr_to_ansistr inzwischen verschwunden, stattdessen tritt die AV jetzt wahlweise bei fpc_ansistr_incr_ref oder fpc_ansistr_decr_ref auf. Wenn ich die Strings komplett rauslasse, kommt die AV bei fpc_copy. TAIRec ist hierbei:
// RunGeneration
procedure RunGeneration(var gen: TGeneration; out avg: single; out max: TAIRec); var i,j: byte; sum: word; c: shortint; begin for i := 0 to 63 do RunMatch(gen[i],false); for i := 0 to 63 do RunMatch(gen[i],true); SortGen(gen); c := 0; for i := 63 downto 0 do if (gen[i].score>=225) then c := 64-i; for j := 0 to 30 do begin for i := 0 to c-1 do RunMatch(gen[63-i],false); for i := 0 to c-1 do RunMatch(gen[63-i],true); end; SortGen(gen); max.score := 0; sum := 0; for i := 0 to 63 do begin if gen[i].score>max.score then max := gen[i]; sum += gen[i].score; end; avg := sum/64; end; // RunMatch procedure RunMatch(var g: TAIRec; const r: boolean); var party: TParty; pl1,pl2,wp: PPlayer; drv: TEvoDrive; q,is1: Boolean; c: byte; begin party := TParty.Create; drv := TEvoDrive.Create(party); pl1 := MakePlayer(drv,GenSID); pl1^.Name := g.Genetics.Name; // <-- Hier fpc_shortstr_to_ansistr/fpc_ansistr_incr_ref/fpc_ansistr_decr_ref drv.SetAI(g.Genetics); // <-- und hier schlägt fpc_copy fehl, wenn obere Zeile rauskommentiert ist party.SetPlayer1(pl1); if r then pl2 := MakePlayer(TRandomizer.Create(party),GenSID) else pl2 := MakePlayer(TPrimAIPlayer.Create(party),GenSID); pl2^.Name := 'Bernd'; party.SetPlayer2(pl2); q := false; is1 := false; if Random(2)=0 then begin is1 := true; wp := pl2; pl2 := pl1; pl1 := wp; end; c := 0; try repeat if party.TurnClosed then begin party.Proceed(wp); is1 := not is1; if is1 then Inc(c); end else q := true; until assigned(wp) or q; if q and is1 then Dec(c); if assigned(wp) and (wp^.id=SID_DEAD) then c := 15 else if assigned(wp) and (wp^.id=pl1^.id) then c := 20; g.Score += (c*c) div 2; finally party.Free; DismissPlayer(pl1); DismissPlayer(pl2); end; Inc(pcount); end;
Delphi-Quellcode:
PEvoState = ^TEvoState;
TEvoState = record Action, OnTrue, OnFalse: byte; end; PEvoAI = ^TEvoAI; TEvoAI = record //Name: AnsiString; States: array[0..127] of TEvoState; end; Zitat:
Delphi-Quellcode:
und vor
{$mode objfpc}
Delphi-Quellcode:
. Zusätzlich ist auch der Parameter -Sh gesetzt.
{$coperators on}
Zitat:
|
AW: Wo kommt auf einmal "fpc_shortstr_to_ansistr" her?
Zitat:
Delphi-Quellcode:
Wie wird PPlayer innerhalb von MakePlayer angelegt und wie ist es (und sein Basistyp) definiert? Wie ist p.Genetics definiert?
// RunGeneration
procedure RunGeneration(var gen: TGeneration; out avg: single; out max: TAIRec); var i,j: byte; sum: word; c: shortint; begin for i := 0 to 63 do RunMatch(gen[i],false); for i := 0 to 63 do RunMatch(gen[i],true); SortGen(gen); c := 0; for i := 63 downto 0 do if (gen[i].score>=225) then c := 64-i; for j := 0 to 30 do begin for i := 0 to c-1 do RunMatch(gen[63-i],false); for i := 0 to c-1 do RunMatch(gen[63-i],true); end; SortGen(gen); max.score := 0; sum := 0; for i := 0 to 63 do begin if gen[i].score>max.score then max := gen[i]; sum += gen[i].score; end; avg := sum/64; end; // RunMatch procedure RunMatch(var g: TAIRec; const r: boolean); var party: TParty; pl1,pl2,wp: PPlayer; drv: TEvoDrive; q,is1: Boolean; c: byte; begin party := TParty.Create; drv := TEvoDrive.Create(party); pl1 := MakePlayer(drv,GenSID); pl1^.Name := g.Genetics.Name; // <-- Hier fpc_shortstr_to_ansistr/fpc_ansistr_incr_ref/fpc_ansistr_decr_ref drv.SetAI(g.Genetics); // <-- und hier schlägt fpc_copy fehl, wenn obere Zeile rauskommentiert ist party.SetPlayer1(pl1); if r then pl2 := MakePlayer(TRandomizer.Create(party),GenSID) else pl2 := MakePlayer(TPrimAIPlayer.Create(party),GenSID); pl2^.Name := 'Bernd'; party.SetPlayer2(pl2); q := false; is1 := false; if Random(2)=0 then begin is1 := true; wp := pl2; pl2 := pl1; pl1 := wp; end; c := 0; try repeat if party.TurnClosed then begin party.Proceed(wp); is1 := not is1; if is1 then Inc(c); end else q := true; until assigned(wp) or q; if q and is1 then Dec(c); if assigned(wp) and (wp^.id=SID_DEAD) then c := 15 else if assigned(wp) and (wp^.id=pl1^.id) then c := 20; g.Score += (c*c) div 2; finally party.Free; DismissPlayer(pl1); DismissPlayer(pl2); end; Inc(pcount); end; Gruß, Sven |
AW: Wo kommt auf einmal "fpc_shortstr_to_ansistr" her?
Zitat:
Delphi-Quellcode:
type
PEvoState = ^TEvoState; TEvoState = record Action, OnTrue, OnFalse: byte; end; PEvoAI = ^TEvoAI; TEvoAI = record Name: AnsiString; States: array[0..127] of TEvoState; end; PPlayer = ^TPlayer; TPlayer = record id: TPlayerID; intf: IPlayer; name: AnsiString; end; IPlayer = interface procedure GrantVoice(const voice: TVoice); overload; procedure GrantVoice(const voice: TVoice; const piece: TPiece); overload; end; PSafeID = ^TSafeID; TSafeID = record st, nd, rd: Longword; end; PPlayerID = PSafeID; TPlayerID = TSafeID; function MakePlayer(const intf: IPlayer; const pid: TPlayerID): PPlayer; begin New(Result); Resptr.intf := intf; Resptr.id := pid; end; procedure DismissPlayer(const p: PPlayer); begin Dispose(p); end; procedure TEvoDrive.SetAI(const ai: TEvoAI); begin FGenetics := ai; // alternativ: // FGenetics.States := ai.States; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:51 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