Prinzipielle Frage zur Veränderung von Pointern
-
Hallo Forum,
das Topic ist vielleicht ein wenig komisch gewählt, aber mir ist nichts Vernünftigeres dafür eingefallen. Ich möchte lediglich wissen, in welchen Fällen es vor kommt, dass ein Zeiger sich nach Aufruf einer Funktion verändert hat, in der er nicht angefasst wurde. Da muss (natürlich) irgendwo etwas falsch sein, ich weiß leider aber nicht, wo. Das Problem daran ist, dass ich eigentlich nicht viel Code posten kann (sind mittlerweile 1300 loc) und der Fehler theoretisch überall stecken könnte.
Zum Hintergrund: Ich implementiere gerade einen R-Baum. Der Fehler tritt niemals beim einfach einfügen (inklusive Splits der Knoten, etc) auf. Jedoch, wenn ich Knoten gelöscht habe, hinterher neue einfüge, kommt es vor, dass, jedoch lediglich beim einem Split eines inneren Knotens, manche Zeiger in einer Methode, die, wie gesagt, auf den "kaputten" Bereich keinen Einfluss nimmt, auf falsche Elemente zeigt.
Jetzt wollte ich im Allgemeinen fragen, an welchen Stellen, ich da nachsuchen muss, um die Fehler beseitigen zu können. Hänge da quasi heute schon den ganzen Tag drüber und komme nicht weiter.Viele Grüße
-
mit "der Zeiger ändert sich", meinst du, dass der Zeiger plötzlich irgndwo anders zeigt oder ändert sich der Inhalt, worauf der Zeiger zeigt?
-
Hallo,
also prinzipiell zeigt der Zeiger auf was anderes. Der Inhalt ändert sich eigentlich nicht dabei. (Also der Inhalt ändert sich schon, da der Zeiger offensichtlich woanders hin zeigt).
-
und du bist sicher, dass du keine Funktion aufrufst, die einen Zeiger auf deinen Zeiger erwartet?
-
Hi,
also, ich poste dir mal eben den Quelltext, bei welchem der Zeiger verändert wird:// next is a struct containing of a rtree_node * and a linkedlistelem * next = next_picker(&(node)->elements, first_group, second_group); // put the content to the linked list if (linkedlist_insert_back(&next.where->elements, next.what->content) < 0) { return retval; } ++next.where->element_count; if(!next.where->is_leaf) { // ptr is a pointer to an rtree_node for saving the content that is void * ptr = next.what->content; ptr->parent = next.where; }
Ich kann nur so viel sagen, dass vor dem Quelltext der Zeiger auf parent des Knotens "where" auf den eigentlichen parent zeigt und danach zeigt er auf sich selbst. Ich verstehe das Ganze leider überhaupt nicht, weswegen ich denke, dass der Speicherfehler woanders her kommt. Es passiert beim split, wo herausgesucht wird, zu welchem der beiden neu geteilten Knoten das Kind-Element hinzugefügt wird.
-
Vorden schrieb:
...
next = next_picker(&(node)->elements, first_group, second_group);
...
if (linkedlist_insert_back(&next.where->elements, next.what->content)
...^^hier übergibst du adressen, ist also nicht auszuschliessen, dass die elemente verändert werden.
btw, wenn du so keinen fehleer sehen kannst, dann häng dich mit 'nem debugger rein und geh den code schrittweise durch.
-
Debugger ist ein gutes Stichwort ... wenn man vorher schon weiß, welcher Zeiger irgendwann irgendwo verändert wird, kann man einen Data Breakpoint aufsetzen. Der springt genau in dem Moment an, in dem die überwachte Speicherstelle geändert wird.
-
Ich hab schon rein debugged und alles, allerdings ist es eben genau die Stelle, an der der parent gesetzt wird, wo mir der Zeiger verändert wird. Die Adresse der Liste übergebe ich, allerdings ist dort nirgends ein Verweis auf den Knoten drin, der wird vorher gelöscht. Diese Liste ist die, die auf die resultierenden Knoten aufgeteilt werden soll. Der Zeiger, der in where drin steht ist vorab mittels malloc() neu aufgebaut worden und ist den Listen somit nicht bekannt. Trotzdem erhalte ich diesen komischen Effekt. Mir geht es prinzipiell auch bloß darum zu erfahren, an welchen Stellen solche Effekte auftreten können, um gezielter danach suchen zu können.
Danke so weit.EDIT: data breakpoint ist ein gutes Stichwort, muss nur finden, wie ich einen solchen setzen kann (Eclipse CDT)
-
diesen komischen effekt hat man, wenn über speicher-/arraygrenzen hinaus daten geschrieben werden. der betreffende bezeichner kann sich dabei sonstwo im quellcode befinden, wenn es passiert.
zu suche:
variableninhalt überwachen und die haltepunkte auf den anfang der fuktionen setzten. ist eine funktion der übeltäter, kannst du die suche verfeinern und die haltepunkte innerhalb dieser funktion setzen, usw.
-
Vorden schrieb:
EDIT: data breakpoint ist ein gutes Stichwort, muss nur finden, wie ich einen solchen setzen kann (Eclipse CDT)
wenn debuggen mit eclipe/cdt zu fummelig ist, bau an den verdächtigen stellen paar printf-ausgaben ein, die dir die inhalte der pointer ausgeben, istwert, sollwert wert usw.
-
Denk dran, dass du bei Funktionen prinzipiell Zeigerkopien erhälst. Wenn du sowas wie
void meinefunktion(char *c){ c = "quatsch"; } char *c = "hallo"; meinefunktion(c); printf(c);
bastelst, dann ist das c das du übergibst und das c das meinefunktion kriegt verschieden und der Code gibt "hallo" aus, und nicht "quatsch".
Damit ändert sich ein Zeiger, der in eine Funktion übergeben wird, prinzipiell niemals, selbst wenn er explizit überschrieben wird.
Wenn du also nicht willst, dass ein Zeiger von einer Funktion überschrieben wird brauchst du nur aufzupassen, dass du keinen Zeiger auf den Zeiger übergibst, und das sollte mit minimalen Änderungen machbar sein.