Tote Pointer vernichten...
-
Ich code in C eine DLL und arbeite mit Structuren.
Nun erstelle ich dort ein Objekt "A" mit malloc.
Später erstelle ich Objekt "B" auch mit malloc.Ich möchte Objekt "B" mit Objekt "A" verbinden indem ich void* pointer auf Objekt "A" setzte.
So nun wird Objekt "A" irgendwann gelöscht - was passiert dann mit Objekt "B"? Es bleibt doch eine Verbindung zu der Adresse von Objekt "A" ???
Das Problem was ich habe ist, dass ich unzählige Objekte habe. Es können auch mehrere Objekte auf 1 Objekt linken.
Wer kennt Tipps für mich wie ich es handeln kann (und es soll nicht langsam sein).
-
So nun wird Objekt "A" irgendwann gelöscht - was passiert dann mit Objekt "B"? Es bleibt doch eine Verbindung zu der Adresse von Objekt "A" ???
Wenn du Objekt "A" löscht, passiert mit "B" erstmal gar nichts. Du musst nur aufpassen das "B" nicht mehr mit der Adresse von "A" arbeitet, da der Speicher ja gelöscht wurde.
Du musst dir halt irgendwie merken wer auf "A" zeigt und wenn "A" gelöscht wird musst du allen, die darauf verweisen, "Bescheid sagen".
-
hm... d.h. ich muß bei jedem objekt eine liste führen wohin es linkt und eine liste von wo gelinkt wurde... das erfordert mehr speicher...
alternativ könnte ich eine globale liste machen wo jede verlinkung registriert wird... dann wäre es langsamer, da ich ganze liste abarbeiten muß von allen objekten...
sowas wie:void register_link(void* source, void* dest)
void register_del (void* object) //object wäre source oder dest - es wird nach beiden gesucht und dann gelöscht...
-
Vielleicht könnte man bessere Ratschläge geben wenn du dein eigentliches Problem (also die Datenstruktur die du umsetzen willst/umgesetzt hast) etwas näher beschreibst?
-
TheShadow2000 schrieb:
hm... d.h. ich muß bei jedem objekt eine liste führen wohin es linkt und eine liste von wo gelinkt wurde...
Hi,
als erstes solltest Du Dir Gedanken über "ownership" machen: Wem gehört das Objekt und wer nutzt es nur ? Um diese Aufgabe herum solltest Du Dein Programm strukturieren. Wenn Du das nicht klar hast, gehst Du schnell in einem Sumpf von "free()-Handling" ("hab ich den jetzt schon gelöscht ?" und "Was, wenn ich den schon gelöscht habe ?") unter. Am einfachsten ist es, wenn Du die Erzeugung und Vernichtung der Objekte kapselst.
Gruß,
Simon2.
-
Simon2 schrieb:
Am einfachsten ist es, wenn Du die Erzeugung und Vernichtung der Objekte kapselst.
hatte mal langeweile, hier ein kleines beispiel
(objekte haben einen internen zähler)struct object { int refcount; // hier kann noch mehr rein }; void access_object (struct object **obj) { // object existiert schon -> zugriffe zählen if (*obj) { (*obj)->refcount++; return; } // ...andernfalls neues object anlegen *obj = malloc(sizeof (struct object)); if (!*obj) return; // neues objekt beginnt bei 1 (*obj)->refcount = 1; } void release_object (struct object **obj) { // object schon weg? ->nix mehr machen if (*obj == 0) return; (*obj)->refcount--; // letzter verweis? -> objekt löschen if ((*obj)->refcount == 0) { free (*obj); *obj = 0; } } void test (struct object **obj) { if (*obj == 0) printf ("object %p existiert nicht\n", obj); else printf ("object %p/%p, refcount: %d\n", obj, *obj, (*obj)->refcount); } void main (void) { struct object *o1 = 0; // muss mit 0 initialisiert sein // testing... test (&o1); access_object (&o1); test (&o1); access_object (&o1); test (&o1); access_object (&o1); test (&o1); access_object (&o1); test (&o1); release_object (&o1); test (&o1); release_object (&o1); test (&o1); release_object (&o1); test (&o1); release_object (&o1); test (&o1); release_object (&o1); test (&o1); }
-
hm... @net
so wie ich jetzt deinen code verstehe - erstellt du ein objekt und tust so als ob du was verlinkst und dann zählst du bei dem objekt den counter hoch... soweit gut...
so nun stell dir vor du löscht nicht die referenzen und machst nicht den counter runter (wie in deiner simulation), sondern du löschst das objekt selbst.
nach deinem code darf erst gelöscht werden, wenn keine referenzen vorhanden sind - dann muß ich so ein Objekt in der Zwischenzeit aber als ungültig markieren...
jetzt die frage - was ist sinnvoller. ich halte es gefährlicher so ein objekt weiter im speicher zu halten - besser wäre es meiner meinung nach es zu löschen und alle verlinkungen sofort zu entfernen...
ich hab weiter nachgedacht - und ich denke es ist mehr daten-overhead bei jedem objekt listen mitzuführen welche objekte gelinkt wurden...
stattdessen halte ich die idee besser einen zentralen code einzubauen, der verlinkungen registriert. der code müsste aber wohl anders aussehen wie ich oben gepostet habe - eher so:
void register_object (void* sourceobj, void* destobj, void* linkfrom)
bei sourceobj/destobj ist es klar - die objekte die mit malloc erzeugt wurden.
und linkfrom ist speicheradresse von wo gelinkt wird (also eigenschaft innerhalb von sourceobj)nachteil gibt es bei der lösung - wenn 90% der objekte nicht verlinkt sind, so muß trotzdem die registrierung abgearbeitet werden... dies könnte man mit countern lösen...
-
TheShadow2000 schrieb:
so wie ich jetzt deinen code verstehe - erstellt du ein objekt und tust so als ob du was verlinkst und dann zählst du bei dem objekt den counter hoch... soweit gut...
äääh, naja, das ist so'ne demo wie man automatisch objekte erzeugen und löschen kann (wegen des postings von simon 'objektkapselung'). verlinkt wird nix
TheShadow2000 schrieb:
so nun stell dir vor du löscht nicht die referenzen und machst nicht den counter runter (wie in deiner simulation), sondern du löschst das objekt selbst.
das darf man nicht machen. das würde das ganze prinzip vergewaltigen
TheShadow2000 schrieb:
nach deinem code darf erst gelöscht werden, wenn keine referenzen vorhanden sind - dann muß ich so ein Objekt in der Zwischenzeit aber als ungültig markieren...
nee, gelöscht wird automatisch. wenn genauso oft 'release_object' aufgerufen wird wie 'access_object' dann isses wech.