Autor Beitrag
Simon Joker
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 236
Erhaltene Danke: 1



BeitragVerfasst: Mi 12.05.04 18:49 
Hallo

Ich hatte heute ein seltsames Phänomen, daß mich fast zur Verzweiflung getrieben hat.
Nach der Implementation eines dynamischen Arrays, traten sporadische Abstürze und Zugriffsverletzungen auf. Die klassischen Anzeichen für einen überschrittenen Speicherbereich beim dyn. Array. Also alles kontroliert, aber nichts gefunden!
Nach einem Rückbau und einer schrittweisen Neuimplementierung habe ich die Ursache gefunden. Dummerweise verstehe ich sie nicht!

Deshalb hier die Defintion die den Chrash verursachte:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
    <span style="font-weight: bold">{VERSION 1}</span>
    TWayPicDataRec = packed record
      ImgIndex :word;
      ...
      {snip - unwichtig}
      ...
    end;    

    TFieldProp = record
      ...
      {snip - unwichtig}
      ...      
      PicData      : array of TWayPicDataRec; //->diese Definition kill die Application
    end;
    TFieldPropArray = array of TFieldProp;

    <span style="font-weight: bold">{VERSION 2}</span>
    TWayPicDataRec = packed record
      ImgIndex :word;
      ...
      {snip - unwichtig}
      ...
    end;
    TWayPicDataArray = array of TWayPicDataRec;

    TFieldProp = record
      ...
      {snip - unwichtig}
      ...
      PicData      : TWayPicDataArray; //->diese Definition funktionierert
    end;
    TFieldPropArray = array of TFieldProp;


Wie gesagt Version 1 killt mir das Programm. Version 2 dagegen funktioniert anstandslos. Das krude daran ist, das es noch nicht mal eine Variable dieser Definition geben muß um den Effekt hervorzurufen.

Was ist der Unterschied der beiden Definitionen? Eigentlich sollten sie doch gleichwertig sein.

Danke für die Aufklärung.
Da_Knuddelbaer
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 485



BeitragVerfasst: Do 13.05.04 20:24 
Hi Simon,

nun, ich will dich ja net ärgern oder so, aber bei mir funzen beide Versionen. Es liegt also kein Fehler in deinen Auszügen vor. Der Fehler muss wo anders liegen, in irgendeiner Stelle in deinem Source. Fakt ist, es funzen beide Deklarationen.

Ich würd einfach nochmal die ganzen Parts, wo du deine Records verwendest, durchforsten. Denk dran die Größe muss ständig mit SetLength angepasst werden sobald du Einträge in das Array einfügst oder entfernst (besser ist das auch beim entfernen, ja :)) und der Index beginnt bei 0.

Greetz,
Da_Knuddelbaer
Simon Joker Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 236
Erhaltene Danke: 1



BeitragVerfasst: Do 13.05.04 21:04 
Hi Da_Knuddelbaer

Tja, das ist die Antwort, die ich am meisten gefürchtet habe. Es sind ja nur 1,2 mb Source! :roll: Aber as der Fehler an einer beliebigen anderen Stelle ist, kann ich mir eigentlich nicht vorstellen, da die Zocke auch bei recht ausführlichen Test keine Mucken gemacht hat (bis jetzt).

Noch mal zur Erklärung. Die Schnipsel der Definition gehören zu einen quasi statischen Array, das nur beim Laden einmal aus einer Konfigurationsdatei erstellt wird und dann nur noch ausgelesen wird. Zugriff auf die ArrayStruktur nur nach Low/High-Prüfung des Indexes, ob die Konfigdatei unverändert und richtig ist kann ich ich schließlich nicht garantieren :? .

Der Punkt, der mich etwas verstört, ist das nur das Einfügen der Definition den Effekt verursachte. Er trat also auf, bevor ich auch nur eine Variable dieser Definition erzeugt hatte. Sollte eine Definition, die nicht verwendet wird, nicht vom Compiler entfernt werden?

Im Forum wurde schon mal ein solch seltsames Verhalten von Dyn. Arrays und SetLength angesprochen, aber ich finde den Beitrag jetzt nicht mehr. Ist auch bestimmt auch schon anderthalb Jahre her.
Da_Knuddelbaer
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 485



BeitragVerfasst: Fr 14.05.04 09:30 
Juten morgen :)

der Compiler entfernt lediglich leere Prozeduren, die von einem Steuerelement verwendet werden. Deklarationen entfernt er nicht, würde mich auch immer nerven wenn ich mir mühevoll nen Typ deklariere und der Compiler den dann wieder killt *gg*

Delphi so an sich hat sowieso einige merkwürdige Verhalten, siehe auch ShowMessage.

Also du deklarierst einfach nur
ausblenden Delphi-Quelltext
1:
PicData      : array of TWayPicDataRec;					


anstatt
ausblenden Delphi-Quelltext
1:
PicData      : TWayPicDataRec;					


und genau dann gibt der Compiler einen Fehler aus?
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Fr 14.05.04 11:53 
Da_Knuddelbaer hat folgendes geschrieben:
der Compiler entfernt lediglich leere Prozeduren, die von einem Steuerelement verwendet werden. Deklarationen entfernt er nicht, würde mich auch immer nerven wenn ich mir mühevoll nen Typ deklariere und der Compiler den dann wieder killt *gg*

Der Linker entfernt alles was nicht verwendet und daher auch nicht gebraucht wird..!

Zitat:
Delphi so an sich hat sowieso einige merkwürdige Verhalten, siehe auch ShowMessage.

Was meinst du da??

@Simon Joker: soll das heißen du verwendest diesen Datentyp nirgendwo in deinem Programm..? Wann genau tritt denn die Zugriffsverletzung auf? Ganz am Anfang, ganz am Ende, irgendwo zwischendurch..?

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
Simon Joker Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 236
Erhaltene Danke: 1



BeitragVerfasst: Fr 14.05.04 12:56 
Hi

@Da_Knuddelbaer
Wie Motzi schon sagte, entsorgt der Compiler/Linker Proceduren, Definitionen usw, die nie verwendet werden.

@Motzi
Zitat:
soll das heißen du verwendest diesen Datentyp nirgendwo in deinem Programm..?

Korrekt! Zumindest als ich nach dem Fehler gesucht habe. Nach dem die Implementation des erwähnten Teilstückes in die Hose ging, habe ich wieder alles herausgenommen(Spiel funktionierte wieder) und dann halt schrittweise wieder eingefügt. Der der Typendefinition habe ich begonnen. Und siehe da es reichte diesen Typ einzufügen und es stürtzte ab. Ich hatte noch keine Variable dieses Typs definiert!

Zitat:
Wann genau tritt denn die Zugriffsverletzung auf? Ganz am Anfang, ganz am Ende, irgendwo zwischendurch..?

Der Absturtz erfolgte immer nach/bei der Verwendung von SetLength. Dabei kommt es zu keiner Fehlermeldung sonder die entsprechende Procedur wird schlicht verlassen. Soweit ich feststellen kann werden Daten im Heap überschrieben. Die Arraygrenzen sind dabei aber in einem gültigen Bereich. Verwende ich Version 2 der Definition oder kommentiere die Definition ganz aus, funktioniert exakt der gleiche Array-Konstruktor ohne Probleme. Der zeitpunkt des Absturtzes ist auch nicht konstant machmal trat er beim 50zigsten Arrayelement auf, manchmal beim 70zigsten.