AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen FreePascal FreePascal Wo kommt auf einmal "fpc_shortstr_to_ansistr" her?
Thema durchsuchen
Ansicht
Themen-Optionen

Wo kommt auf einmal "fpc_shortstr_to_ansistr" her?

Ein Thema von implementation · begonnen am 14. Jan 2012 · letzter Beitrag vom 17. Jan 2012
Antwort Antwort
Benutzerbild von implementation
implementation

Registriert seit: 5. Mai 2008
940 Beiträge
 
FreePascal / Lazarus
 
#1

Wo kommt auf einmal "fpc_shortstr_to_ansistr" her?

  Alt 14. Jan 2012, 17:54
Ich sitze hier gemütlich an einem Programmierprojekt für die Schule (ich soll Bei Google suchenQuarto nachprogrammieren und versuche mich an einer evolutionären KI ), da fliegt mir plötzlich ne AV um die Ohren:
Zitat:
An unhandled exception occurred at $0000000000407FE5 :
EAccessViolation : Access violation
$0000000000407FE5
$0000000000443D03
$00000000004005BC line 66 of evogen.pp
Nach ein bisschen erfolglosen Rumprobieren bin ich dann mal über die Mapfile den Adressen auf den Grund gegangen: Bei $407FE5 handelt es sich um fpc_shortstr_to_ansistr, bei $443D03 um eine eigene Prozedur (RunGeneration), bei $4005BC um PASCALMAIN.
Ich wundere mich über fpc_shortstr_to_ansistr und überprüfe nochmal, ob überall {$longstrings on} 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.

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:
call   fpc_shortstr_to_ansistr@PLT
Davor ein FPC_ANSISTR_DECR_REF@PLT und danach ein FPC_ANSISTR_INCR_REF@PLT und ein FPC_ANSISTR_DECR_REF@PLT.

Wo kann das herkommen? Ich zerbreche mir daran jetzt schon 1,5 Stunden den Kopf und finde den Punkt nicht
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
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
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#2

AW: Wo kommt auf einmal "fpc_shortstr_to_ansistr" her?

  Alt 15. Jan 2012, 02:52
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 ... und vorher eine 1+ verteilen.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Benutzerbild von implementation
implementation

Registriert seit: 5. Mai 2008
940 Beiträge
 
FreePascal / Lazarus
 
#3

AW: Wo kommt auf einmal "fpc_shortstr_to_ansistr" her?

  Alt 15. Jan 2012, 10:50
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 ... und vorher eine 1+ verteilen.
Den versteh ich jetzt nicht ganz. Das ganze tritt in meinem eigenen Code auf, nicht in seinem


[ADD]
Mittlerweile hab ich fpc_shortstr_to_ansistr wegbekommen, indem ich string durch AnsiString ersetzt habe. Dafür tritt die AV jetzt in FPC_ANSISTR_INCR_REF auf

Geändert von implementation (15. Jan 2012 um 11:04 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von JamesTKirk
JamesTKirk

Registriert seit: 9. Sep 2004
Ort: München
604 Beiträge
 
FreePascal / Lazarus
 
#4

AW: Wo kommt auf einmal "fpc_shortstr_to_ansistr" her?

  Alt 15. Jan 2012, 20:28
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
Sven
[Free Pascal Compiler Entwickler]
this post is printed on 100% recycled electrons
  Mit Zitat antworten Zitat
Benutzerbild von implementation
implementation

Registriert seit: 5. Mai 2008
940 Beiträge
 
FreePascal / Lazarus
 
#5

AW: Wo kommt auf einmal "fpc_shortstr_to_ansistr" her?

  Alt 15. Jan 2012, 20:43
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.
Hab ich auch schon verwendet, aber die fpc_*-Routinen sind nicht mitverzeichnet und deshalb muss ich so oder so suchen (beim Zitat im Anfangspost kann man ja auch sehen, dass die Option aktiv war)

Zitat:
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.
In RunGeneration selbst trat dies nicht auf, sondern in einer anderen Routine, die von RunGeneration aufgerufen wird, nämlich RunMatch. Seltsam, dass diese jedoch nicht im Calltrace verzeichnet ist.
Delphi-Quellcode:
// 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;
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:
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:
Wo hast du denn {$longstrings on} gesetzt? Vor einem eventuellen {$mode delphi/objfpc} oder danach? Wenn davor, dann setze das mal überall dahinter hin.
In allen Projektdateien nach {$mode objfpc} und vor {$coperators on} . Zusätzlich ist auch der Parameter -Sh gesetzt.

Zitat:
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).
Habe ich vorhin auch schon ausprobiert, gleiches Problem.

Geändert von implementation (15. Jan 2012 um 20:45 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von JamesTKirk
JamesTKirk

Registriert seit: 9. Sep 2004
Ort: München
604 Beiträge
 
FreePascal / Lazarus
 
#6

AW: Wo kommt auf einmal "fpc_shortstr_to_ansistr" her?

  Alt 17. Jan 2012, 09:25
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.
Hab ich auch schon verwendet, aber die fpc_*-Routinen sind nicht mitverzeichnet und deshalb muss ich so oder so suchen (beim Zitat im Anfangspost kann man ja auch sehen, dass die Option aktiv war)
Stimmt...

Delphi-Quellcode:
// 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;
Wie wird PPlayer innerhalb von MakePlayer angelegt und wie ist es (und sein Basistyp) definiert? Wie ist p.Genetics definiert?

Gruß,
Sven
Sven
[Free Pascal Compiler Entwickler]
this post is printed on 100% recycled electrons
  Mit Zitat antworten Zitat
Benutzerbild von implementation
implementation

Registriert seit: 5. Mai 2008
940 Beiträge
 
FreePascal / Lazarus
 
#7

AW: Wo kommt auf einmal "fpc_shortstr_to_ansistr" her?

  Alt 17. Jan 2012, 13:46
Wie wird PPlayer innerhalb von MakePlayer angelegt und wie ist es (und sein Basistyp) definiert? Wie ist p.Genetics definiert?
Au, das wollte ich gestern eigentlich gleich mit hinschreiben, hab's dann wohl doch vergessen.
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;
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:31 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz