Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Mi Jul 16, 2025 23:11

Foren-Übersicht » Programmierung » Allgemein
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 20 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Autor Nachricht
 Betreff des Beitrags: Probleme mit dynamischem Array
BeitragVerfasst: Mi Jan 14, 2004 17:43 
Offline
DGL Member
Benutzeravatar

Registriert: So Dez 21, 2003 17:36
Beiträge: 141
Hey,
Ich bin grad dabei, mich mit nem DeleD-Level Loader (zumindest die Procedure dazu) zu versuchen, und um die einzelnen Verticen zu laden, habe ich dynamische Arrays genommen:

Code:
  1.  
  2. type
  3.   TypeVertexInfo = record
  4.                   x,y,z : single;
  5.                 end;
  6.   TypePolygon = record
  7.                   textureid : integer;
  8.                 end;
  9.   TypeObject = record
  10.               visible, snapping, UVlock : boolean;
  11.               groupID : integer;
  12.               polygon : array of TypePolygon;
  13.               VertexInfo : Array of TypeVertexInfo;
  14.               vertices : integer;
  15.               polygons : integer;
  16.             end;
  17.  


Code:
  1.  
  2.       map : record
  3.           texturepack : string;
  4.           objects : integer;
  5.           obj : array of TypeObject;
  6.         end;
  7.  


So. Soweit dazu. So sieht meine bisherige Lade-Routine aus:
( Sie ist natürlich noch nicht fertig, bin ja bisher erst bis zu den Verticen gekommen.)

Code:
  1.  
  2.  
  3. procedure LoadMap(mapname : string);
  4. var s : string;
  5.  
  6. begin
  7.   assign(f,mapname);
  8.   reset(f);
  9.  
  10.     readln(f,s); //DeleD Map File
  11.     readln(f,s); //Version
  12.     readln(f,s); //0 0 0 0
  13.     readln(f,s); //Texturepack
  14.       map.texturepack:=s;
  15.     readln(f,s); //Object Count
  16.       map.objects:=strtoint(s);
  17.  
  18.     initialize(map.obj); //hab mal gelesen, dass man das machen soll....
  19.     setlength(map.obj,map.objects); //hier wird dem ersten Array die Größe zugewiesen
  20.  
  21.     for i:=1 to {map.objects} 1 do begin
  22.       readln(f,s); //Obektname, nicht wichtig
  23.       readln(f,s); //used internally, nicht wichtig
  24.       readln(f,s); //Visible?
  25.       if (s='-1') then map.obj[i].visible:=true
  26.                         else map.obj[i].visible:=false;
  27.       readln(f,s); //Snapping?
  28.       if (s='0') then map.obj[i].snapping:=true
  29.                         else map.obj[i].snapping:=false;
  30.       readln(f,s); //GroupID
  31.       map.obj[i].groupID:=strtoint(s);
  32.       readln(f,s); //LockUV
  33.       if (s='-1') then map.obj[i].UVLock:=false
  34.                         else map.obj[i].UVLock:=true;
  35.  
  36.       readln(f,s); //Userspecified Info
  37.       s:='';
  38.       readln(f,s); //Number of vertices
  39.       a:=strtoint(s);
  40.       map.obj[i].vertices:=a;
  41.  
  42.       initialize(map.obj[i].VertexInfo);
  43.       setlength(map.obj[i].VertexInfo, map.obj[i].vertices); //Zweites Array
  44.  
  45.       for a:=1 to map.obj[i].vertices do begin
  46.         //X-Value of Vertices
  47.         read(f,s12);
  48.         while (s12[0]=' ') do delete(s12,0,1);
  49.  
  50.         map.obj[i].vertexinfo[a].x:=strtoint(s12);
  51.         //Y-Value of Vertices
  52.         read(f,s12);
  53.  
  54.         while (s12[0]=' ') do delete(s12,0,1);
  55.         map.obj[i].vertexinfo[a].y:=strtoint(s12);
  56.         //Z-Value of Vertices
  57.         readln(f,s12);
  58.  
  59.         while (s12[0]=' ') do delete(s12,0,1);
  60.         map.obj[i].vertexinfo[a].z:=strtoint(s12);
  61.       end;
  62.     ShowMessage('Vertex-Laden abgeschlossen');
  63.  
  64.  
  65.  
  66.     end;
  67.  
  68.   close(f);
  69. end;


So. Das Problem:
Beim starten geht alles schön fein, hab das natürlich in meine FormCreate Prozedur gepackt, beim Idle läuft auch alles fein (ich habe die map noch nicht implementiert, wird also auch nicht gerendert), wenn ich das Ding allerdings abbreche, also beende, kommt:
Zitat:
Project test.exe raised exception class EInvalidPointer with Message 'Invalid pointer operation'. Process stopped. Use Step or Run zu continue.

Kein Problem dachte ich, setz ich mal eben ein showmessage am anfang der OnDestroy-Prozedur, als ich das dann allerdings mal wieder gestartet hab, stell ich fest, dass das scheinbar gar nicht soweit kommt!?

Irgendein Fehler im Code? Hab ich mal wieder was falsch gemacht?

Danke.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Jan 14, 2004 17:53 
Offline
DGL Member
Benutzeravatar

Registriert: Di Jun 24, 2003 19:09
Beiträge: 732
Code:
  1.  
  2.  ... for i:=1 to ...
  3.  

dynamische Arrays beginnen bei 0 und hören dann logischerweise bei map.objects -1 wieder auf...
Wenn du ein array der länge 5 hast dann ist [0] der erste und [4] der letzte Eintrag...

Woher der Fehler beim schließen kommt läßt sich schwer sagen. Löscht du die Arrays irgendwann wieder? Was passiert in Form.OnClose?


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Jan 14, 2004 18:01 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Dieser Feher "Invalid Pointer Operation" resultiert aus der bereichsverletzung mit dem dynamischen array. Evtl könnte es sinnvoll sein, wenn du wärend der Entwicklungszeit die Bereichsprüfung (Projekt -> Optionen -> Compiler) einschaltest. Dann bekommst du sofort bei Verletzung einen Fehler.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Jan 14, 2004 18:03 
Offline
DGL Member
Benutzeravatar

Registriert: So Dez 21, 2003 17:36
Beiträge: 141
*Hust* Okay, das scheint zu wirken :D

In der FormDestroy Methode passiert folgendes:

Code:
  1.  
  2. showmessage('Test');
  3. // Renderkontext deaktiveren
  4. DeactivateRenderingContext;
  5. // Renderkontext \"befreien\"
  6. wglDeleteContext(RC);
  7. // Erhaltenen Gerätekontext auch wieder freigeben
  8. ReleaseDC(Handle, DC);
  9. // Falls wir im Vollbild sind, Bildschirmmodus wieder zurücksetzen
  10. ChangeDisplaySettings(devmode(nil^), 0);
  11. showmessage('Test');
  12. for i:=0 to {map.objects}0 do begin
  13.     for a:=1 to map.obj[i].vertices do setlength(map.obj[i].VertexInfo, 0);
  14. end;
  15. showmessage('Test');
  16. for i:=0 to map.objects-1 do begin
  17.   setlength(map.obj, 0);
  18. end;
  19. showmessage('Test');
  20.  


Also naja, der Fehler kommt zumindest nicht mehr, aber die Messages werden mir auch nicht angezeigt :?


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Jan 14, 2004 18:08 
Offline
DGL Member

Registriert: Mo Jan 20, 2003 20:10
Beiträge: 424
Wohnort: nähe Starnberg
Kurze Frage, wird der reservierte Speicher von dynamisch reservierte Arrays nicht automatisch freigegeben? War immer der Meinung, dass ich diese nicht extra freigeben müßte. Wenn Pointer in dem Array sind, da muss ich natürlich den Pointer selber freigeben, aber doch nicht der reservierte Platz für den Pointer selber, oder?

Gruß
KidPaddle

_________________
http://www.seban.de


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Jan 14, 2004 18:17 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 20, 2003 09:15
Beiträge: 70
Wohnort: Italien
Dynamische Arrays werden dann freigegeben, wenn man sie auf nil setzt, oder ihre Lände auf 0 setzt

_________________
"Phantasie ist wichtiger als Wissen, denn Wissen ist begrenzt" Albert Einstein


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Jan 14, 2004 18:19 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Dynamische Arrays haben genauso wie Strings einen Referenzzähler, den Delphi automatisch erhöht bzw erniedrigt. Bei Funktionen wird z.B. intern extra ein try finally Block drumherumgebaut um die Dekrementierung der Zählers sicherzustellen. Records und Klassen mit dynamischen Arrays erhalten Type Informationen damit die finalize Funktion den Speicher korrekt freigeben kann.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Jan 14, 2004 18:37 
Offline
DGL Member

Registriert: So Okt 12, 2003 14:53
Beiträge: 74
Wo wir schonmal beim Thema sind:
Kann mir jemand erklären wann und warum man ein dyn. Array manchmal mit der Function Initialize und Finalize "bearbeiten" muss? Ich hatte nähmlich letztens sowas geproggt, wo dann in einem rekord ein dyn. array enthalten war, aber den speicher für dieses Rekord hab ich mir erst mit dem GetMem befehl (also durch Pointer) geholt. Als ich das aber so gemacht hab, gab es ein Problem mit dem Array, und in einem Forum sagte mir jemand das ich den initialize befehl dafür benutzen soll. Aber er hatte wohl (verständlicherweise) keine lust mir zu erklären warum man das machen muss :D .
Naja ich hoffe ihr habt die gedult mir das zu erklären *g*. Die System.pas ist ja schon recht umfangreich und garnicht so leicht da die richtigen stellen rauszusuchen und zu verstehen. :roll:


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Jan 14, 2004 18:54 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Ein dynamisches Array ist ein Zeiger auf einen so einen Block mit den Daten und dem Referenzzähler. Bei einem leeren dynamischen Array zeigt der Zeiger auf nil. Wenn man mit getmem Speicher belegt, dann stehen da nicht zwangsläufig Nullen drin, so daß bei späteren Zuweisungen an das Array versucht wird über diesen falschen Zeiger den Referenzähler von dem vermeintlich alten Daten zu erniedrigen. Wenn man eine Variable in einer Klasse oder lokal auf dem Stack deklariert, dann übernimmt Delphi diese Arbeit. Wenn man den Speicher selber z.B. über einen Zeiger auf einen Record mit einem dynamischen Array verwaltet, dann kann man ja nicht mehr so direkt nachverfolgen wie viele Referenzen es jetzt eigentlich auf das Array gibt, denn der Zeiger wird ja als ganz normaler Zeiger weitergegeben. Daher muß man dann selber finalize aufrufen, damit der Referenzzähler dekrementiert wird, und falls er 0 wird, also diese die letzte Referenz war, der Speicher freigegeben wird. Wenn man da selber eingreift kann man sich viele seltsame Fehler einhandeln. Ich habe z.B. mal solch einen record mit Nullen überschrieben und an einer ganz anderen Stelle im Programm gab es dann eine Schutzverletzung.
Immer wenn man den Speicher für solch einen Record oder Array mit dynamischen Arrays selber mit getmem belegt muß man initialize und finalize benutzen. Daher ist es vielleicht günstiger wenn man solche automatische Verwaltung und selber belegten Speicher nicht unbedingt mischt, weil dann die Vorteile verloren gehen und man immer auf initialize und finalize achten muß.
Anstelle von getmem und freemem kann man auch new und dispose benutzen. Bei diesen Funktionen wird initialize und finalize nach Bedarf automatisch aufgerufen.
Die langen, also normalen Strings, funktionieren nach dem gleichen Prinzip.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Jan 14, 2004 20:00 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
KidPaddle hat geschrieben:
Kurze Frage, wird der reservierte Speicher von dynamisch reservierte Arrays nicht automatisch freigegeben? War immer der Meinung, dass ich diese nicht extra freigeben müßte. Wenn Pointer in dem Array sind, da muss ich natürlich den Pointer selber freigeben, aber doch nicht der reservierte Platz für den Pointer selber, oder?


Spätestens durch die Garbage Collection vom Betriebssystem wird so etwas dann frei gegeben. Aber darauf sollte man nach Möglichkeit verzichten. ;-)

Auf der ganz sicheren Seite ist man wenn man ihm eine Länge von 0 verpasst. Bzw so etwas irgendwie kappselt. Also in einer Klasse zum Bleistifft. Dann kann man selber ganz gut bestimmen bis wohin etwas existiert und wann nicht mehr.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Jan 14, 2004 20:11 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Wenn die Elemente eines dynamischen Arrays wieder dynamische Arrays oder records mit dynamischen Arrays sind, dann werden die natürlich genauso wie Strings mit freigeben. Wenn man in dem Array beliebige Zeiger hat, dann wird natürlich nur der Speicherplatz den die Zeiger in dem Array belegen automatisch freigegeben.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Jan 15, 2004 08:27 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Jul 12, 2002 07:15
Beiträge: 916
Wohnort: Dietzhölztal / Hessen
Programmiersprache: C/C++, Obj-C
@Dynamische Arrays: Also ich weiss ja nicht genau, wass Du mit dem Initialize-Bereich machen willst, aber ansich ist die Arbeit mit Dynamischen Arrays recht einfach und stabil. Hab' das ganze schon öfters verwendet und bin dabei folgendermaßen vorgegangen:

Code:
  1.  
  2. var
  3.   x : array of TIrgendwas;
  4.   i : Integer:
  5. begin
  6.   SetLength(x, 10);  // Die Größe des Arrays setzen.
  7.   for i := 0 to 9 do // Wie schon erwähnt: dyn. Arrays immer 0-Basierend
  8.     x[i].blabla := sonstwas;
  9.   ...
  10.   Finalize(x);       // Das dyn. Array wieder freigeben.
  11. end;
  12.  


So hab' ichs aus der Delphi-Hilfe und so funktionierts bei mir auch ohne Probleme. Lass auf jeden Fall das Initialize weg, da du damit das array bereits initialisierts (auf Größe von eins), dann mit Setlength einen neuen Speicherbereich reservierst und zuweist und den mit initialize erstellten Speicher nicht mehr freigibst. Schau einfach mal in der Delphi Hilfe nach.

_________________
Und was würdest Du tun, wenn Du wüsstest, dass morgen Dein letzter Tag auf dieser Erde ist?


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Jan 15, 2004 10:51 
Offline
DGL Member

Registriert: So Okt 12, 2003 14:53
Beiträge: 74
Danke für die Antwort. Ich glaube ich habs verstanden.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Jan 15, 2004 11:18 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Dez 13, 2002 12:18
Beiträge: 1063
@Speicherfreigabe
MemCheck ( http://v.mahon.free.fr/pro/freeware/memcheck/ ) wirkt oft Wunder und ist auch bei eigentlich fertigen Projekten manchmal ein wahrer Augenöffner :wink:

_________________
Viel Spaß beim Programmieren,
Mars
http://www.basegraph.com/


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Jan 15, 2004 16:23 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Weil das dynamische Array x in diesem Beispiel direkt deklariert ist, braucht man das nicht extra mit finalize freizugeben. Am Ende der Funktion wird automatisch DynArrayClear aufgerufen.
Die Frage bezog sich nur auf dynamische Arrays, die sich innerhalb von Speicher befinden, der mit getmem belegt worden ist.
Initialize ist nur dafür da, daß das Array am Anfang auch leer bzw. nil ist. Bei lokalen Variablen, wird das aber beim Beginn der Funktion bereits gemacht.


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 20 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Foren-Übersicht » Programmierung » Allgemein


Wer ist online?

Mitglieder in diesem Forum: Majestic-12 [Bot] und 8 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.011s | 16 Queries | GZIP : On ]