.
|
|
| Autor | Beitrag |
|---|---|
|
050 05.12.2002, 09:11 Kriz |
Hä? Der macht was? Eine Liste nach leeren Objekten durchsuchen? Was verstehst du unter leeren Objekten? Wenn ein Element aus der Liste entfernt wird durch remove() o.ä. , dann sollte auch zugesichert sein, daß dieses Element auch durch die Listenverwaltung vollständig vom Heap gelöscht wurde. Nur einfach das Element aus der Liste entlassen bringt nichts, da du sonst ein "verwaistes Objekt" auf dem Heap rumliegen hast, das nur Speicherplatz verschwendet und zu dem du absolut keinerlei Zugriff mehr hast zum nachträglichen Löschen! Leere Objekte, also Elemente ohne Inhalt, sollten tunlichst nicht in der Liste länger verweilen als nötig, da die Liste sonst unnötig aufgebläht wird (Speicher frisst) und die relative Zugriffszeit ebenfalls erhöht wird. Leere Objekte ans Ende der Liste zu transferieren bringt dir nämlich garnichts, denn normalerweise werden neue Elemente ans Ende angehängt. Wenn du allerdings durch deinen "Manager" bereits z.B. 200 leere Elemente ans Ende bewegt hast, dann müßte deine Liste theoretisch bei einem toBegin() o.ä. erstmal 200 leere, nutzlose Elemente durchgehen plus die vorderen Elemente der Liste, da der Zeiger auf das aktuelle Element (normalerweise) beim Hinzufügen eines Elements auf dasselbige zeigt. Anderer Punkt: Wenn du ein Element aus der List entfernst (also definitiv löschst), kannst du niemals sicher sein, das der dort freigegebene Platz auch wieder zum Füllen mit einem neuen Element bereitsteht. Die Heapverwaltung übernimmt das RTS (Runtime System) des Programms und darauf hast du keinen Einfluß. Geschwindigkeitsmäßig sollte eine Liste nur dann genommen werden, wenn dynamischen Arrays oder sowas benutzt werden sollen. Denn das Umkopieren dynamischer Strukturen wie Arrays infolge einer Hinzufügung ist zeitaufwendiger als das Hinzufügen eines Listenelements. Anders sieht das bei statischen Arrays aus. Dort ist mittels Zeigerarithmetik der Zugriff schneller als mit einer Liste. --K:R-I)Z++ |
|
Profil || Suche |
|
051 05.12.2002, 09:51 King of Darkness |
ok danke, das hilft mir etwas weiter, Coding Center --- Tutorials über Programmierung und andere Themen |
|
Profil || Suche |
|
052 05.12.2002, 15:06 Prefect |
Alles was du malloc()st mußt du auch free()en. "Leere" Elemente in einer Liste zu lassen ist unsinnig, das erhöht nur den Verwaltungsaufwand, lieber gleich free()en. Andererseits gibt es Situationen, in denen du dich durchaus um die Speicherverwaltung sorgen mußt. malloc() und free() können recht langsam sein, dazu kommt dann auch noch eine Heapfragmentation wenn du kleine Strukturen andauernd löscht und wieder erstellst. Diese Methode mit der Empty-List ist durchaus machbar, in deinem Fall (Partikelsystem) aber nicht unbedingt sinnvoll. Für ein Partikelsystem könntest du zum Beispiel ein ungeordnetes dynamisches Array verwenden. Da sind, genauso wie bei einer LL, Löschen und Einfügen O(1)-Algorithmen. Allerdings entfällt der Aufruf der Heaproutinen, die sehr unberechenbar sind. Außerdem befinden sich alle Partikel in einem zusammenhängenden Speicherbereich - der Cache wird es dir danken. cu, Widelands - Gemütliche Aufbaustrategie, Free Software |
|
Profil || Suche |
|
053 05.12.2002, 15:16 King of Darkness |
mhhh auch ne möglichkeit nur habe ich mit nem dynamischen array noch nicht gearbeitet, wie funktioniert sowas objekt *array[]; oder wie ? um nochmal zur liste zu kommen, ich habe ein problem wie man ja weis ;) und zwar wenn ich das ding free()e dann is ds teil immer nochdrin, gedanken habe ich mir da schon gemacht aber da kommt nur müll raus: pObjekt->next = pObjekt->next->next; nur geht das irgendwie nich :( komisches satz das sein ! --Coding Center --- Tutorials über Programmierung und andere Themen |
|
Profil || Suche |
|
054 06.12.2002, 09:06 Kriz |
Ich mach mal ne C Variante:
Was tut sich hier? Zuerst wird mal geprüft, ob der übergebene Elementzeiger ungleich NULL ist, also existiert (eine Funktion create() z.B. erledigt das Erzeugen eines neuen Elements, welches dann ja ungleich NULL wird). Wenn ja, dann werden zwei Hilfszeiger pNext und pPrev erzeugt. pNext zeigt auf den Nachfolger des Elements, während pPrev auf dessen Vorgänger zeigt. Hier spielt es keine Rolle, ob der Nachfolger und/oder Vorgänger NULL ist. Jetzt ist die Verkettung erstmal gesichert. Danach wird das Element gelöscht. Anschließend wird geprüft, ob der Vorgänger existiert. Falls ja, wird der next-Zeiger des Vorgängers auf den Nachfolger gerichtet. Das gleiche passiert umgekehrt mit dem Nachfolger, der auf den Vorgänger des Elements gerichtet wird. Danach setzt eine Funktion toEnd() den globalen (!) AktuellesElement Zeiger auf das letzten, verfügbare Element der Liste. Das ist sicherer als das aktuelle Element auf den Nachfolger oder Vorgänger des gelöschten Elements zu setzen. Aber das kannst du ja realisieren wie du willst. --K:R-I)Z++ |
|
Profil || Suche |
|
055 06.12.2002, 15:16 Prefect |
Das dynamische Array sieht in etwa so aus:
Auf die einzelnen Elemente im Array kannst du dann ganz normal mit array[n] zugreifen.
Natürlich sollte das Array bei Gelegenheit auch wieder verkleinert werden (mit realloc()) wenn array_size sehr viel kleiner ist als array_reserved. Allerdings macht es durchaus Sinn, komfortabel viel Platz frei zu lassen damit man realloc() nicht so oft aufrufen muß - realloc() kann sehr teuer kommen, weil es potentiell das ganze Array in der Gegend herumkopiert. Auch mußt du berücksichtigen, daß die Elemente von remove() verschoben werden, d.h. die Indizes sind nicht konstant. Für ein Partikelsystem, bei dem die Indizes keine Rolle spielen, ist ein solches dynamisches Array allerdings ganz günstig. Prinzipiell kannst du übrigens auch das std::vector-Template verwenden. Allerdings kriegst du optimale Performance wahrscheinlich nur, wenn du das Array per Hand managest und einen besser angepaßten Algorithmus verwendest um zu entscheiden, wann das Array per realloc() vergrößert oder verkleinert werden soll. cu, Widelands - Gemütliche Aufbaustrategie, Free Software |
|
Profil || Suche |
|
056 06.12.2002, 16:32 the_viking |
Bei Partikel-systemen würd ich warten, bis das ganze tot ist und dann das GANZE array entfernen, stell dir vor du müsstes alle 10ms 1 von 1000 partikeln entferenen.. und sooo groß ist der speicherbedarf nun auch nicht.... bei 1000 partikeln, á la: WER SICH UM DIESE 19!KB GEDANKEN MACHT, SOLLTE MAL ZUM PSYCHATER!!! ( auf einem 128MBRam-frei rechner könnte man dan ca. 7000 Partikel-Systeme laufen lassen, ausser man benutzt HW-VertexBuffer) --thx, cu, MfG the_viking (( My =]=H=O=M=E=> Page! )) |
|
Profil || Suche |
|
057 06.12.2002, 20:40 Prefect |
Anscheinend hast du die von mir vorgeschlagene Methode nicht wirklich verstanden. Wie gesagt, remove() und insert() sind _beides_ O(1)-Algorithmen. Wenn du die Partikel nicht entfernst erhältst du ein fragmentiertes Array, und du mußt dich darum kümmern welche Partikel-Struktur nun ein gültiges Partikel enthält und welches nicht. Außerdem wird die insert()-Operation um einiges komplexer, weil du erst nach nicht verwendeten Partikel-Strukturen suchen mußt. Übrigens würde ich auch nicht jedes Mal, wenn ein Partikel eingefügt oder gelöscht wird eine Heapmanagement-Routine aufrufen (habe ich auch nie behauptet), denn das wäre _natürlich_ dumm. Wenn auch die Argumentation über den Speicherplatz etwas lame ist, ich würde da eher über die Unberechenbarkeit (performance-mässig) von Heaproutinen argumentieren. Whatever... BTW, deine Rechnung ist inkorrekt. Wenn ein Vektor aus 3 floats besteht braucht die von dir gezeigte Struktur 4 * (3*4) + 4 = 52 Bytes. cu, Widelands - Gemütliche Aufbaustrategie, Free Software |
|
Profil || Suche |
|
058 09.12.2002, 09:26 King of Darkness |
mal jetz mal wieder zu meiner linked list class objekt unsigned long Länge; es ist nich alles nur das was ich noch im kopf habe ;) Coding Center --- Tutorials über Programmierung und andere Themen |
|
Profil || Suche |
|
059 09.12.2002, 11:22 K-Putt |
Ich bin zwar kein Profi, aber seit wann funktionieren Umlaute in Variablennamen? --Rambo Engineer @ Drippy's 2fort - finest TFC 1.5 || Bild Upload || The world's most advanced open source database |
|
Profil || Suche |
|
060 10.12.2002, 08:53 King of Darkness |
das stimmt das is ja auch aus dem kopf, natürlich habe ich im richtigen code laenge stehen ;) Coding Center --- Tutorials über Programmierung und andere Themen |
|
Profil || Suche |
|
061 10.12.2002, 10:52 Kriz |
Hm, hm, hm... Ich schreib dir mal ne Klassendefinition auf für eine doppelt verkettete Liste. Sie ist nicht-virtuell, sollte daher nicht unbedingt abgeleitet und überladen und nachher mit wilden Objektzeigern attackiert werden. Durch die nicht-virtuelle Definition erhöht sich die Geschwindigkeit der Klasse (zum Nachteil der Ableitbarkeit und dem restlichen OOP Gelümmel). Außerdem verzichtet sie auf einen Kopierkonstruktor. Die Daten werden als void-Zeiger gespeichert. Es ist nur darauf zu achten, daß beim "getten" des Inhalts richtig zurückgecastet wird. Das mußt du also schon selber übernehmen!
Hm, um dir jetzt die konkrete Arbeitsweise aller Methoden untereinander zu erklären, müßte DarthPaul erstmal die maximale Zeichenanzahl pro Post drastisch erhöhen *ggg*. Aber laß mal deine Kreativität spielen (ich weiß, daß dieser Satz gerade SEHR entmutigend war, aber nur durch Try-and-error kommt man ordentlich weiter). Dieser Ansatz ist nur einer von vielen in C++!!! Cu --K:R-I)Z++ Dieser Beitrag wurde am 10.12.2002 um 10:52 von Kriz bearbeitet. |
|
Profil || Suche |
|
062 10.12.2002, 10:59 King of Darkness |
ja das is mir alles klar und du bringst auch ein paar nette idee, aber ich denke das löst nicht mein problem :(, ich kann ja mal morgen den code posten (ca 250 bis 300 zeilen) aber vorher schau ich noch mal ganz genau mit debug durch ;) und wenn ich ihn poste kann ich dann ja gleich noch ein anderes weniger problematisches problem posten ;) --Coding Center --- Tutorials über Programmierung und andere Themen |
|
Profil || Suche |
|
063 10.12.2002, 15:10 Tron |
kriz, ich bin _entsetzt_! und vom aufbau her sollten sich die listenelemente auch nicht selbst verwalten... --'KEINE PANIK' - aus der Triologie in fuenf Baenden von Douglas Adams 'FÜR DEINN FERD' - aus 'Gevatter Tod' von Terry Pratchett |
|
Profil || Suche |
|
064 11.12.2002, 08:43 Kriz |
I know. Aber er wollte ja was über eine Klasse wissen... Nun ja, man kann eine Liste entweder als Inhalt + Manager implementieren oder als Inhalt und als separaten Manager. Ich bevorzuge die erste Variante, weil es irgendwie herausfordender ist, hehehe! =) --K:R-I)Z++ Dieser Beitrag wurde am 11.12.2002 um 08:44 von Kriz bearbeitet. |
|
Profil || Suche |
|
065 11.12.2002, 09:21 King of Darkness |
is doch denke ich mal nich das problem kommt drauf an was der manager machen soll ;) Coding Center --- Tutorials über Programmierung und andere Themen Dieser Beitrag wurde am 11.12.2002 um 09:25 von King of Darkness bearbeitet. |
|
Profil || Suche |
|
066 11.12.2002, 09:25 King of Darkness |
///////////////////////und jetz die main mit der ich das ganze teste so und jezt nich böse sein aber ich will ne konkrete antwort warum der den speicher nicht frei gibt wenn ich die funtion destroy aufrufe, und vieleicht noch ein paar tips, sorry wenn das jetz ein bischen viel war --Coding Center --- Tutorials über Programmierung und andere Themen |
|
Profil || Suche |
|
067 11.12.2002, 16:59 dp Administrator |
das forum hat nicht umsonst ne zeichenbegrenzung, das nächste mal bitte linken.. -- |
|
Profil || Suche |
|
068 11.12.2002, 17:15 Tron |
ARGH! new <-> delete _NIEMALS_ mischen falls dir der unterschied zwischen den 3 paaren nicht bekannt ist, fehlen dir wichtige grundlagen bzgl. dynamischer speicheralloziierung!
urgs! wenn eine funktion true/false zurueckgibt, dann soll sie auch als bool deklariert werden. die implementierungen von AddObjekt und InsertObjekt sind mir ziemlich schleierhaft, scheinen mir auch fehlerbehaftet zu sein, aber so genau hab ich die mir noch net angesehen. --'KEINE PANIK' - aus der Triologie in fuenf Baenden von Douglas Adams 'FÜR DEINN FERD' - aus 'Gevatter Tod' von Terry Pratchett |
|
Profil || Suche |
|
069 12.12.2002, 11:32 King of Darkness |
mhhh also gut ok das mit dem alloc werde ich ändern liste *pTemp; das mit der do schleife, kann ja dort egal sein da das ja ehn nur ein sinniges testproggi ist, in dem ich die liste teste, aber wenn ich die richtig nutze kann ich das ja mit do machen und wieso immer perfix und nich suffix is das nich egal, ok was das letzte objekt betrifft mhhh ? und was ist schleierhaft ? fehlerhaft kann es nich sein da es geht, es gibt zwar fehler die nich auffallen aber ich bin der meinung das es geht, vieleicht nicht die beste lösung, aber es geht --Coding Center --- Tutorials über Programmierung und andere Themen |
|
Profil || Suche |
|
070 12.12.2002, 14:49 Prefect |
Also, mit new reservierte Speicherblöcke darf man einfach deswegen nicht mit free() freigeben, weil das laut dem Standard nicht geht. Klar - in manchen Implementationen geht's ohne Probleme, aber new und malloc() holen sich ihren Speicher in anderen Implementationen vielleicht von zwei verschiedenen Heaps. Und wenn du dann mit delete ein per malloc() reservierten Speicherblock freigeben willst kriegst du Ärger, weil delete den Speicherblock eben im eigenen Heap erwartet. liste *pTemp; Das mit Postfix vs. Prefix-In/Dekrement kann ich ehrlich gesagt auch nicht nachvollziehen. Gibt's da eine rationale Begründung? Wenn es Fehler gibt, die nicht auffallen, dann ist das Programm per Definition fehlerhaft. Wenn du solche Fehler durchgehen läßt mit der Begründung, daß das Programm ja im Moment funktioniert, wird das relativ schnell übel enden. Irgendwann werden diese Fehler nämlich mit einem neu eingebauten Programmteil auf eine unvorhergesehende Weise interagieren und du wirst die Freude haben, absolut unverständliche Abstürze debuggen zu dürfen. BTW: char* pChar = new char; cu, Widelands - Gemütliche Aufbaustrategie, Free Software |
|
Profil || Suche |
|
071 12.12.2002, 16:46 Tron |
postfix ist, wenn der optimierer nicht schlau ist nunmal langsamer (hier ist das zwar voellig egal und heutige compiler sind so schlau, aber es geht hier um's prinzip!) objekte, die einen konstruktor und/oder destruktor haben, der nicht leer ist _niemals_ mit malloc/free handhaben, da diese den konstruktor/destruktor nicht aufrufen! und das mit den verschiedenen heaps sagte prefect ja schon. bezueglich AddObjekt: das letzte if ist _immer_ wahr, falls es erreicht wird. (ergibt sich aus dem ersten if und daraus, dass Laenge immer >= 0 ist) bezueglich InsertObjekt: der konstruktor deiner klasse objektliste scheint auch fehler zu enthalten, du erzeugst dort 3 liste-objekte als erstes, aktuelles und letztes, die nichts voneinander wissen, das stinkt nach potentiellen verwaisten objekten. --'KEINE PANIK' - aus der Triologie in fuenf Baenden von Douglas Adams 'FÜR DEINN FERD' - aus 'Gevatter Tod' von Terry Pratchett |
|
Profil || Suche |
|
072 13.12.2002, 08:51 King of Darkness |
wahhh danke ;) zum letzten: wenn du ein objekt an das ende anfügen willst nimmst du addobjekt ansonsten insert ;) ich habe die free()´s duch delete´s ersetzt und der speicher wird besser behandelt, aber eben nur besser und nich gut- das problem ist immer noch das wenn ich den speicher frei gebe es mir nicht angezeigt wird (im taskmanager von win2k) dor steig der speicher fast immer, wenn ich allerdings 330000 objekte in liste lade und die dann wieder raus kicke bleibt die ramverwendung gleich hoch, wenn ich aber wieder 110000 objekte hinzufüge reserviert er keinen neuen speicher, bei den nächsten 110000 objekte etwas speicher und dann bei den nächsten 110000, das habe ich mal so lange betrieben bis mein rechner überlastet war am ende hatte ich 770000 objekte in der liste und habe den speicher wieder frei gegeben, ne zeit gewartet, und der ram blieb immernoch bei rund 700 MB, programm beendet dann dung er wieder runter auf rund 90 MB (etwas viel ich weiss), wo ist allso sein problem ? wieso gibt er den speicher nicht an windoof zurück oder is das win zu blöd dazu das zu erkennen das da wieder speicher frei geben ist? oder is das proggie fehlerhaft (ihr werde sicher sagen proggi fehler) --Coding Center --- Tutorials über Programmierung und andere Themen |
|
Profil || Suche |
|
073 13.12.2002, 14:34 Prefect |
Ah ja, das mit Prefix/Postfix stimmt natürlich. Bei Postfix muß der Compiler im Prinzip ein neues Objekt erstellen um den alten Zustand zurückgeben zu können, bei Prefix nicht. Solange alle Funktionen inline gehandelt wird dürfte es natürlich keinen Unterschied machen, aber das Prinzip zählt :) cu, Widelands - Gemütliche Aufbaustrategie, Free Software |
|
Profil || Suche |
|
074 13.12.2002, 16:46 Mazze |
Jepp, im Stroustrup steht, dass man z.B. cu BattleTech-MOD: |
|
Profil || Suche |
|

