Simple Frage zu Referenz in C++ und Qt
lima-city → Forum → Programmiersprachen → C/C++ und D
adresse
code
compiler
eintreten
erwarten
funktion
objekt
parameter
problem
problematik
set
speichern
terminal
test
text
url
ursache
verweis
zeiger
zeile
-
Hallo zusammen,
ich brauche mal eure Hilfe:
Was ist der Unterschied zwischen:
QString szItem = "Test"; QString& szItemAnd = szItem; szItem = QString(szItemAnd);
und
?QString szItem = "Test";
In szItem sollte doch das Selbe stehen, oder?
Beides wird einem Datenbankprogramm gegeben:
-Beim ersten stürzt das Programm ab.
-Beim zweiten läuft es so wie gewünscht.
Grüße
Sebastian
PS:
Bitte keine Antwort:
-Poste doch mal den kompletten Code. -> Das macht keinen Sinn, weil ich genau dies als Ursache herausgearbeitet habe.
- Bitte nur antworten, wenn man wirklich eine Idee hat (Compiler VS2008).
Beitrag zuletzt geändert: 4.8.2014 15:23:55 von sebastian-online -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage
-
Hi,
ich war mit dieser problematik bisher noch nie konfrontiert, aber ich kann mir folgendes denken:
QString braucht laut Dokumentation(http://qt-project.org/doc/qt-4.8/qstring.html) Unicode, standard-Abspeicher-Zeichensatz ist UTF-8 im VS. Da ich zu dieser problematik jetzt auch keine Ahnung habe, aber weiß, wie du da schnell dran rankommst, empfehle ich dir folgendes:
hau auf die Zeile
QString szItem = "Test";
einen breakpoint. Sobald er da reinstepped, gehst du mit F11 die einzelbnen schritte durch, bis der Fehler fliegt.
Es könnte auch sein, dass der & Parameter überladen wurde und deswegen was anderes rauskommt, als was du erwarten würdest. Schau dir dazu oben gepostete Doku an...
das wär so der erste Verdacht, den ich habe als jemand, der zwar C kann, aber QT noch nie was mit gemacht hat... -
Danke für deine Mühe.
Also:
- Der &-operator ist nicht überschrieben.
Debuggen geht nicht, da das Ganze über das Netzwerk ausgeführt wird mit unterschiedlichen Stationen (Terminals). Es ließen sich auch nur mit Mühe einzelne Funktionen isolieren.
Ich vermute mal, dass es irgend ein Compilerfehler ist. Ich habe jetzt alles mit Zeigern laufen.
Viele Grüße
Sebastian -
Hallo sebastian-online,
dein Problem im ersten Beispiel kommt folgendermaßen zustande:
Die Zeile
QString szItem = "Test";
erzeugt ein QString-Objekt auf dem Stack, welche beim eintreten in die Funktion initialisiert wird. Damit auch alles wieder ordentlich aufgeräumt wird baut der Compiler am Ende der Funktion eine Destruktoraufruf ein.
Hierbei ist zu beachten, dass QString für den Text Speicher auf dem Heap reserviert, welcher im Destruktor freigegeben wird.
Der Bug ist dann die folgende Zeile:
szItem = QString(szItemAnd);
Hierbei wird ein neues/zweites QString-Objekt erzeugt und dieses als flache Kopie über szItem kopiert. Dabei wird insbesondere die Speicheradresse des Textes im Heap überschrieben. D.h. das erste und das zweite QString-Objekt verweisen jetzt auf den Text-Speicherbereich des zweiten QString-Objektes. Die Adresse des ersten Objektes ist verloren und man hat daher ein Memory-Leak.
Der Compiler merkt aber, dass das zweite QString-Objekt nach dieser Zeile nicht weiter benötigt wird, weshalb er gleich nach dieser Zeile einen Destruktor-Aufruf für das zweite QString-Objekt einfügt.
Jetzt verweist die Heap-Adresse des ersten QString-Objektes auf einen bereits freigegebenen Speicherbereich.
Sofern ein Zugriff auf diesen Speicher nicht bereits zum Programmabsturz führt kommt es spätestens beim Verlassen der Funktion, wenn der Destruktor aufgerufen wird, dazu, weil dieser versucht den bereits freigegenenen Speicherbereich erneut freizugeben.
Hier noch zwei Beispiele zur Illustration mit dem Debugger:
1. Kein Problem:
#include <iostream> using namespace std; class Test { public: Test(int i):value(i) {} Test(const Test& t):value(t.value) {} ~Test(){} int get() { return value; } void set(int i) { value = i; } private: int value; }; int main(int argc, char ** argv) { Test t = 3; cout << t.get() << endl; t = Test(4); cout << t.get() << endl; return 0; }
2. Crash:
#include <iostream> using namespace std; class Test { public: Test(int i) { value = new int[1]; value[0] = i;} Test(const Test& t) {value = new int[1]; value[0] = t.value[0];} ~Test(){ delete[] value; } int get() { return value[0]; } void set(int i) { value[0] = i; } private: int * value; }; int main(int argc, char ** argv) { Test t = 3; cout << t.get() << endl; t = Test(4); cout << t.get() << endl; return 0; }
-
Klasse Antwort! Vielen Dank.
Ich löse jetzt alles über Pointer. Mit den Referenzen gab es auch dann einen Absturz, obwohl ich nicht wieder die selbe Variable (szItem) überschrieben habe. Aber naja.
Vielen Dank
Sebastian -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage