c++ : zeiger aendert spontan die adresse

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
lisan
Beiträge: 658
Registriert: 22.02.2003 19:05:04
Wohnort: Berlin
Kontaktdaten:

c++ : zeiger aendert spontan die adresse

Beitrag von lisan » 20.07.2004 06:38:45

Ich habe folgende struktur:

Code: Alles auswählen

protected:                                         
    struct mp_stack **entryidx[2][2];       
Diese initialisiere ich wie folgt.

Code: Alles auswählen

void Parser::init_stack()
{
struct mp_stack *tmp[2][2];

std::cerr << "init stack" << std::endl;

tmp[0][0] = 0;
tmp[1][0] = 0;
tmp[0][1] = 0;
tmp[1][1] = 0;

entryidx[0][0] = &tmp[0][0];
entryidx[1][0] = &tmp[1][0];
entryidx[0][1] = &tmp[0][1];
entryidx[1][1] = &tmp[1][1];

...
}
Ich rufe nun im Konstruktor der Klasse ParserImpl welche Parser erbt folgendes auf,

Code: Alles auswählen

ParserImpl::ParserImpl() {
        sym_table = NULL;
        init_stack();

        std::cerr << "DEBUG: pre init_table() : Stack adr. : " << *entryidx[0][1] << std::endl;
        std::cerr << "DEBUG: pre init_table() : Stack adr. : " << *entryidx[0][1] << std::endl;
        std::cerr << "DEBUG: pre init_table() : Stack adr. : " << *entryidx[0][1] << std::endl;
        std::cerr << "DEBUG: pre init_table() : Stack adr. : " << *entryidx[0][1] << std::endl;
...
}
Diese Ausgabe ist diese:

Code: Alles auswählen

DEBUG: pre init_table() : Stack adr. : 0
DEBUG: pre init_table() : Stack adr. : 0xbffff880
DEBUG: pre init_table() : Stack adr. : 0xbffff880
DEBUG: pre init_table() : Stack adr. : 0xbffff880
Wenn ich mir das mit gdb bzw. ddd ansehe und durch die cerr stepe sehe ich , dass der code tatsaechlich nacheinander ausgefuehrt wird und kein sprung dazwischen liegt - auch im ddd sehe ich wie die adresse sich von NULL spontan auf das da oben aendert.

Ich sitze schon lange an diesem Problem.

Gruss,
Lisan.

Benutzeravatar
jd
Beiträge: 286
Registriert: 01.07.2003 12:02:33
Wohnort: D->Hessen->MKK

Beitrag von jd » 20.07.2004 08:52:43

Der Gültigkeitsbreich deines Arrays tmp ist auf die Funktion init_stack beschränkt. Es wird auf dem Stack angelegt! Sobald Die Funktion endet, wird die Variable vom Stack genommen, und die Pointer, die Du im entryidx gespeichert hast, zeigen auf einen anderen Inhalt des Stacks (quasi ins Leere). Das sind dann beim Schreiben die klassischen "segfaults". :wink:

Du mußt also dafür sorgen, daß die Strukturen, die Du per Pointer referenzierst auch bestehen bleiben.

Die sauberste Lösung ist es, die Arrays dynamisch zu allokieren und im deconstructor wieder freizugeben.

Benutzeravatar
bitbieger
Beiträge: 179
Registriert: 23.10.2003 08:26:00
Kontaktdaten:

Beitrag von bitbieger » 20.07.2004 08:54:25

Hallo Lisan,

das ist ja echt wilde Rumreferenzierung... ;-)
Du speicherst in deinem Array entryidx die Adressen der einzelnen Einträge von tmp. Da tmp nur eine lokale Variable ist, steht nach dem Verlassen von init_stack() natürlich nur noch Schrott drin.


cu,
bitbieger

Benutzeravatar
lisan
Beiträge: 658
Registriert: 22.02.2003 19:05:04
Wohnort: Berlin
Kontaktdaten:

Beitrag von lisan » 20.07.2004 09:03:20

ich nutze tmp nur, um mit 0 zu initialisieren, das ganze funktioniert nicht wie ihr vermutet.

die tmp zeigen stehen auf 0 und ich uebergebe die adressen der tmp zeiger also 0.
Das macht man oft so bei mehrdimensionalitaet.

Verlasse ich den scope klappt ja alles, allerdings nur eine weile.

Schlagt mir einfach mal vor wie ihr den doppelzeiger mit Nullen initialisiet.

Olaf Dietsche
Beiträge: 520
Registriert: 12.06.2003 23:18:50
Wohnort: Siegburg

Beitrag von Olaf Dietsche » 20.07.2004 09:28:58

Es funktioniert exakt so, wie jd und bitbieger es sagen.

Wenn du die Adressen der tmp Zeiger übergibst, dann übergibst du die Adressen der tmp Zeiger und nichts anderes, schon gar nicht 0.

Wenn du den scope verlässt, dann ist noch alles in Ordnung. Sobald du aber eine Funktion oder Methode aufrufst, wird der Stack und somit dein tmp Array überschrieben und dann klappt es natürlich nicht mehr.

Benutzeravatar
jd
Beiträge: 286
Registriert: 01.07.2003 12:02:33
Wohnort: D->Hessen->MKK

Beitrag von jd » 20.07.2004 09:33:45

ich nutze tmp nur, um mit 0 zu initialisieren, das ganze funktioniert nicht wie ihr vermutet.
Das habe ich auch so verstanden. :wink:
die tmp zeigen stehen auf 0 und ich uebergebe die adressen der tmp zeiger also 0.
Das macht man oft so bei mehrdimensionalitaet.
tmp[ ][ ] ist vom Typ struct mp_stack *! Also ein Pointer. Diesen setzt Du auf 0. Dann nimmst Du aber &tmp[ ][ ] um es an das zweite Array zuzuweisen. Und da hast Du dann einen Pointer auf einen Pointer, was ja anscheinend auch so geplant ist. Nur zeigt dieser struct mp_stack ** Pointer auf ein tmp Element auf dem Stack!

Was willst Du eigentlich erreichen? Sollen die Pointer in entryidx genullt werden, oder sollen sie auf Pointer zeigen, die ihrerseits genullt sind? Wenn Du letzteres willst, dann muß Du die Pointer auch allokieren!

Benutzeravatar
lisan
Beiträge: 658
Registriert: 22.02.2003 19:05:04
Wohnort: Berlin
Kontaktdaten:

Beitrag von lisan » 20.07.2004 09:43:04

Ich habe jetzt einfach adressen festgelegt und nicht alles mit nullen initialisiert - es laeuft denn.

Ich frag mich nur wieso das ding als c version laeuft.

Danke euch.

Antworten