Hallo!
Ich habe ein Programm geschrieben, dass mir einige Daten in einer STL liste speichern soll und die dann auch wieder ausgeben kann. die liste speichert bei mir item objekte die aus zwei INT werten, einem STRING und einem FLOAT bestehen. komischerweise kann ich aber innerhalb meiner STL iteratorschleife nur den ersten INT wert ausgeben, bei den anderen wird mir immer ein SEGMENTATION FAULT angezeigt (zur laufzeit des programms).
hier ein kleiner codeauschnitt mit passendem konsolenoutput:
CODE:
void invoice2::ShowInv(list<item> itL)
{
list<item>::iterator i;
cout<<"----------------------------------------------------"<<endl;
cout<<"Invoice Id: "<<itsId<<endl;
cout<<"Invoice Description: "<<itsDesc<<endl<<endl;;
for(i = itL.begin(); i != itL.end(); i++)
cout<<" Id: "<<i->Getid()<<endl;
cout<<" Description: "<<i->GetDesc()<<endl;
cout<<" Quantity: "<<i->GetQuant()<<endl;
cout<<" Price: "<<i->GetPrice()<<endl<<endl;
}
OUTPUT:
----------------------------------------------------
Invoice Id: 1076074032
Invoice Description:
Id: 1
Id: 2
Segmentation fault
das prog funzt also nur bei Gedid(), obwohl die anderen funktionen (GetDesc()...) ok sein müssten. ich hab sie zumindest erfolgreich getestet...
danke für die mühe das genze zu lesen
liebe grüße
chrise
Segmentation fault
-
-
Probier mal mit (*i)->blabla auf deine Items zuzugreifen.
-
ist nicht (*i).funktionsname das gleiche wie i->funktionsname???
was bedeutet dann (*i)->funktionsname?
-
Zitat
was bedeutet dann (*i)->funktionsname?Falls Pointer auf Objekte gespeichert werden darauf zugreifen.
i->blabla() ist deshalb problematisch, weil Iteratoren abstrakte Pointer sind, und nur die Operatoren *, ==, =!, ++,--,+=,-=, +,-, <,>,<=,>= darauf definiert sind (machmal auch weniger, je nach Iterator Klasse)
Aber NICHT ->
Da Iteratoren aber meist intern als Pointer repäsentiert sind, kompiliert das Zeug, gibt aber meistens nicht das gewünschte Ergebnis.
Hängt stark von der konkreten STL Implementation an.
Btw: Willst Du wirklich bei jedem Aufruf die ganze Liste kopieren ?
Btw^2: Ein weiterer häufiger Pitfall der sehr ähnlich ist:
(*iterator).irgendwas() // ok
*iterator.irgendwas() // falsch -> compiler "denkt" irgendwas() gehört zur Iterator Klasse !
Btw^3: Funktioniert's jetzt mit (*i).GetID() ... ?
Mfg, LB -
Ich habs von diversen Beispielen im Netz, hab damit nämlich auch schon Probleme gehabt.
Der Iterator dürfte auf das Listenelement zeigen, wobei das Listenelement jedoch wieder ein zeiger ist. Drum halt die doppelte Zeigeroperation.
So stell ich mir das vor, auch wenns nicht stimmt, hab ich so das Gefühl, zu wissen, was ich tu. -
Kurz gesagt: iterator->... ist aus STL-Sicht nicht definiert, aber sehrwohl in den tatsächlchen Implementationen.
Daher sollte man es vermeiden, und es ist auch hoffentlich/offensichtlich nirgends bei diversen STL Beispielen zu finden.
Jo, hat mich auch mal ne schlaflose Nacht gekostet -
Danke erstmal für die schnelle Hilfe!
aber es geht leider noch nicht. ich habs mit (*i).funktionsname() versucht, das liefert mir aber wieder die selben probleme wie bei i->funktionsname().
bei (*i)->funktionsname() streikt der compiler:
invoice2.cpp:71: error: base operand of `->' has non-pointer type `item'
weiß jemand was ein segmentation fault sein könnte?
was noch bemerkenswert ist, ist dass ja ein teil des codes funktioniert:
cout<<" Id: "<<i->Getid()<<endl;
wenn ich die restlichen cout ausdrücke weg mache, dann funktioniert das prog....
mfg chrise -
Zitat
bei (*i)->funktionsname() streikt der compiler:Klar, Du speicherst ja keine Pointer auf Objekte.
Auch wenn (*i). versus i-> das Problem nicht löst, laß es auf (*i).
Seg-Fault: In fremden Adressräumen lesen/ (vorallem)schreiben.
Klassiker: a[-1]=0;
Ohne weiteren Code, insbesondere die Klasse, wie die Elemente eingefügt werden etc, kann ich nicht weiterhelfen.
Der Code der gepostet wurde ist IMHO ok, abgesehen vom Iteratorzugriff. Wenn diese Änderung nix hilft ist der Fehler höchstwahrscheinlich anderswo.
Ohne das anderswo zu kennen, recht schwer das zu erraten
Mfg, LB -
versuch mal
for(i = itL.begin(); i <= itL.end(); i++)
statt:
for(i = itL.begin(); i != itL.end(); i++) -
Bug: danke, aber das mag der compiler auch nicht:
invoice2.cpp:71: error: no match for 'operator<=' in 'i <= std::list<_Tp, -
Zitat
for(i = itL.begin(); i <= itL.end(); i++)
Noe, das ist kein wirklich guter Stil.
Und nur für Random Access Iteratoren definiert.
Daher nicht für Listen. -
Zitat von Lord Binary
Seg-Fault: In fremden Adressräumen lesen/ (vorallem)schreiben.
Klassiker: a[-1]=0;wieso muss a[-1] = 0 zwangsläufig zu einem segfault führen?
z.b. (auf Intel)
void foo() {
char a;
char b[2];
char c;b[-1] = 0; // c wird 0
b[3] = 0; // a wird 0
}Segfaults treten dann auf, wenn du auf eine virtuelle Addresse zugreifen willst, die außerhalb des Addressraums deines Programms liegt, oder wenn du auf ein Read-only segment schreiben willst (z.b. ins Code Segement) u. ä. Sachen: die deutsche Übersetzung heißt imho einfach "Speicherzugriffsfehler" (hab ich mal in einer deutsch internationalisierten Shell gesehen).
sehr häufige Quelle für Segfaults sind, dass Pointer nicht richtig initialisiert wurden oder durch eine Funktion initialisiert wurden, die aufgrund eines Fehler NULL zurückgegeben hat, was man nicht überprüft hat (das ist immer ein heißer Tipp!)
-
ICH BIN JA SO EIN DEPP!!!!!
ich hab den fehler jetzt gefunden. wie ich das nur übersehen konnte.
ich muss natürlich alles nach der zeile for(i........ in geschwungene klammern setzten. unglaublich, ich bin wirklich zu blöd zum proggen
zumindest funktioniert es jetzt.
danke allen eifrigen helfern
Lord Binary: die schreibweise hab ich aus nem beispielcode für listen, aber es funktioniert (neuerdings) -
Zitat
wieso muss a[-1] = 0 zwangsläufig zu einem segfault führen?
Muß es natürlich nicht, tut es aber häufig.
Ganz besonders wenn [-1] dann tatäschlich in
[0xfffffffff] übersetzt wird.
(z. b Indexvariable unsigned int definiert)
Nullpointer sind natürlich ein besseres Beispiel.
Chrise:
Auch ich fühl' mich ein bisschen .. naja, ... dämlich ...
das gestern übersehen zu haben *g* -
Zitat von Lord Binary
Muß es natürlich nicht, tut es aber häufig.
Ganz besonders wenn [-1] dann tatäschlich in
[0xfffffffff] übersetzt wird.
(z. b Indexvariable unsigned int definiert)hmm... ich will da ja jetzt nicht drauf rumreiten, aber kann man von einem ANSI C konformen Compiler nicht postulieren, dass
a[-1] = *(a-sizeof(ein_element_aus_a))
ist (sofern das Array dicht gepackt ist i.e. man vom compiler kein besonderes Alignment verlangt hat)?Das signed/unsigned Problem spielt bei Literalen keine Rolle, da integer literale nach ANSI C Standard signed integer sind, man könnte das nur "absichtlich" herbeiführen, wenn man
unsigned int x = (unsigned int)-1;
a[x] = x;
oder sowas macht, aber da würde der Compiler ohne den Cast (der ja ausdrückt, hey, ich weiß schon, was ich tue) sicher schreien (mit einer warning). -
Ja, das stimmt schon alles.
Ich meinte Indexvariablen, ein bisschen zu abstrakt/schlampig/whatever als Konstante geschrieben ...
So in etwa war das gemeint:
unsigned int x=1; int a; char bla[5];
for (a=3; a<7; a++) bla[--x]=0;
Wobei natürlich crash oder nicht crash stark davon abhänig ist, wie der compiler das array übersetzt - auch dieser code muß nicht unbedingt crashen.
(es gibt ja einen offset, nahe bei 2^32 overflows, kan n dann wieder im eigenen Bereich landen)
Geb ja zu daß das Beispiel mit [-1] nicht so ganz perfekt war
Trotzdem sind array underflow und overflows unbestreitbar eher nicht zu empfehlen
Auch wenns mal keinen segfault gibt, überschriebene Variablen (wildwrites) o.ä sind nicht besser, fast im Gegenteil.
Leider passiert das doch recht häufig.
Mfg, LB -
Zitat von Lord Binary
i->blabla() ist deshalb problematisch, weil Iteratoren abstrakte Pointer sind, und nur die Operatoren *, ==, =!, ++,--,+=,-=, +,-, <,>,<=,>= darauf definiert sind (machmal auch weniger, je nach Iterator Klasse)
Aber NICHT ->
Da Iteratoren aber meist intern als Pointer repäsentiert sind, kompiliert das Zeug, gibt aber meistens nicht das gewünschte Ergebnis.
Hängt stark von der konkreten STL Implementation an.Gschichtl.
Ich zitiere den ISO/IEC Standard 14882, Kapitel 24.1, Absatz 1:
<<All iterators i support the expression *i, resulting in a value of some class, enumeration, or builtin type T, called the value type of the iterator. All iterators i for which the expression (*i).m is well-defined, support the expression i->m with the same semantics as (*i).m.>>Falls also du also wirklich einmal einen Unterschied zwischen (*i).m und i->m bemerkt hast, war entweder schon (*i).m nicht wohldefiniert, oder deine Library hatte einen Defekt.
Sogar Autoren von Style-Bibeln wie Scott Meyers verwenden die Syntax i->m.
-
jjan:
Uups, Du hast natürlich recht :o & :hewa:
Danke für die Info/Berichtigung.
Merkwürdig ist es schon, hab das noch nie zuvor gelesen
(it-> equivalent zu (*it). ) , und das waren einige STL-Bücher.
Vorallem wars definitv kein Einzelfall, daß it-> probleme macht,
(*it). nicht.
Egal, meine Schlußfolgerung daraus war wohl nonsense, wieder was gelernt
Mfg, LB
Jetzt mitmachen!
Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!