Rekursiver Zugriff auf Verschachtelte Klassen geht schief -> segmentation fault
-
Hallo,
ich versuche grade verzweifelt eine Funktion eines gSoap-WebServices einzubunden.
Für die Funktion soap_call___ns1__test() muss das Objekt ns1__test gefüllt werden.
Eine ID muss einer Membervariable im "untersten" Objekt gesetzt werden.
Dabei erhalte ich den segmentation fault.Ich würde mich sehr freuen, wenn mir jemand Helfen könnte.
Viele Grüße
int soap_call___ns1__test( struct soap *soap, NULL, // char *endpoint = NULL selects default endpoint for this operation NULL, // char *action = NULL selects default action for this operation _ns1__test* ns1__test, ); /// "testService":test is a complexType. class _ns1__test { public: /// Element incomingTests of type "testService":ArrayOfTests. ns1__ArrayOfTests* incomingTests 1; ///< Required element. /// A handle to the soap struct that manages this instance (automatically set) struct soap *soap ; }; /// "testService":ArrayOfTests is a complexType. class ns1__ArrayOfTests { public: /// Size of array of ns1__Tests* is 0..unbounded int __sizeTests ; /// Pointer to array of length 0..unbounded ns1__Tests* *Tests 0; ///< Nullable pointer. /// A handle to the soap struct that manages this instance (automatically set) struct soap *soap ; }; /// "testService":Tests is a complexType. class ns1__Tests { public: /// Element testin of type "testService":TestIn. ns1__TestIn* testin 1; ///< Nullable pointer. /// A handle to the soap struct that manages this instance (automatically set) struct soap *soap ; }; /// "testService":TestIn is a complexType. class ns1__TestIn { public: /// Element uniqueid of type xs:string. char* id 1; ///< Nullable pointer. /// A handle to the soap struct that manages this instance (automatically set) struct soap *soap ; };Das Füllen des Objekts
_ns1__test* a = new _ns1__test; //für Versuch 1 können die folgenden Init. auskommentiert sein ns1__ArrayOfTests incomingTests = new ns1__ArrayOfTests; ns1__Tests* Tests = new ns1__Tests; ns1__TestIn testin = new ns1__TestIn; //Versuch 1 a->incomingTests->Tests[0]->testin->id = "asdf"; //segmentation fault //Versuch 2 a->incomingTests; incomingTests->Tests[0]; Tests[0]->testin; //segmentation fault testin->id = "asdf"; if( soap_call___ns1__test(soap, NULL, NULL, a) == SOAP_OK ) { ... }
-
Was mir erstmal sofort auffällt:
a->incomingTestsist an der Stelle mit dem segfault uninitialisiert, was wohl der Grund für den Fehler sein dürfte.
Ansonsten Tipp für's nächste Mal: Mit einem Debugger hättest du das in zwei Sekunden rausgefunden
Und noch eine Frage: Was ist denn das für ein Schreibstil? da bekommt man ja Augenkrebs von. Ich bin mir nicht einmal sicher, ob es legales C++ ist, so viele Unterstriche zu verwenden, da gab es irgendeine einschränung, die ich aber nicht auswendig weiß.
-
Zum Augenkrebs: Die Klassen wurden von der gsoap-Routine erstellt.
Hmm ich weiß nicht wie ich das Problem beheben kann.
Wie kann ich das unterste Objekt füllen?
-
Manuel_XY schrieb:
Zum Augenkrebs: Die Klassen wurden von der gsoap-Routine erstellt.
Hmm ich weiß nicht wie ich das Problem beheben kann.
Wie kann ich das unterste Objekt füllen?Kurze Antwort: Indem du die einzelnen Teilstücke, die du mittels
_ns1__test* a = new _ns1__test; ns1__ArrayOfTests incomingTests = new ns1__ArrayOfTests; ns1__Tests* Tests = new ns1__Tests; ns1__TestIn testin = new ns1__TestIn;erzeugt hast, zusammensetzt.
Aber bevor ich zu einer langen Antwort aushole: Warum muss das denn unbedingt so gemacht werden wie du es versuchst? Dein Klassendesign sieht irgendwie sehr ungünstig aus.
-
SeppJ schrieb:
a->incomingTestsist an der Stelle mit dem segfault uninitialisiert, was wohl der Grund für den Fehler sein dürfte.
Kannst das bitte genauer beschreiben?
Die Initialisierung steht doch darüber.
-
Manuel_XY schrieb:
Kannst das bitte genauer beschreiben?
Die Initialisierung steht doch darüber.incomingTests selber ist initialisiert, aber a->incomingTests nicht.
-
Danke dir. Wie meinst zusammensetzen? Ein Beispiel wäre nett.
"Warum muss das denn unbedingt so gemacht werden wie du es versuchst?"
Weil ich die Methoden so geliefert bekomme.
soap_call___ns1__test(...)
Der WebService wurde von einem Systemhaus so erstellt.
-
Manuel_XY schrieb:
Kannst das bitte genauer beschreiben?
Die Initialisierung steht doch darüber.Deine Frage bestätigt, was ich befürchtet habe. Wenn du glaubst, dass
_ns1__test* a = new _ns1__test; ns1__ArrayOfTests incomingTests = new ns1__ArrayOfTests; ns1__Tests* Tests = new ns1__Tests; ns1__TestIn testin = new ns1__TestIn;irgendetwas im Objekt a initialisiert, dann solltest du erstmal nochmal die Grundlagen von C++ lernen, besonders die Grundlagen über Klassen, Member, Scopes, Konstruktoren und ähnliches.
-
Ja bin noch Anfänger und komme aus der C-Welt.
"incomingTests selber ist initialisiert, aber a->incomingTests nicht."
Wie geht das? Muss ich dazu die Klassen manipulieren (weil die wurden von gsoap automatisch gerniert)?Eine kurze Beispiel-Lösung wäre freundlich

-
Manuel_XY schrieb:
Ja bin noch Anfänger und komme aus der C-Welt.
"incomingTests selber ist initialisiert, aber a->incomingTests nicht."
Wie geht das? Muss ich dazu die Klassen manipulieren (weil die wurden von gsoap automatisch gerniert)?Das wäre eine Möglichkeit.
Eine kurze Beispiel-Lösung wäre freundlich

Ungern, denn dann lerst du ja nicht, wo der Fehler liegt. An sich, würde ich die Klassen auch ganz anders designen, damit sowas gar nicht nötig ist.
Aber um dir mal zu erklären, was du gemacht hast, will ich mal ein etwas übersichtlicheres Beispiel bemühen:
struct bar { int daten; // Die eigentlichen Daten } struct foo // Ein struct, dass einen Zeiger auf bar enthält { bar * mbar; } int main(){ foo * a; // Ein Zeiger auf foo, aber noch uninitialisiert, das heißt, a->mbar gibt es noch nicht. a = new foo; // Jetzt zeigt a auf ein Objekt vom Typ foo. a->mbar existiert, ist aber noch uninitialisiert a->mbar = new bar; // a->mbar zeigt jetzt auf ein Objekt vom Typ bar, welches ein int Element namens Daten enthält, welches nicht initialisiert ist a->mbar.daten=1; // Jetzt hat daten im bar Objekt auf das der Zeiger mbar im foo Objekt a zeigt den Wert 1 }Und das war jetzt ein minimal abgespecktes Beispiel von dem was du da machst. Wie du siehst, ist das ein bisschen umständlich. Und hinterher muss das ganze auch wieder freigegeben werden, was nochmal so kompliziert und fehleranfällig ist. Ist halt suboptimales Design.
Wieso eigentlich alle Elemente auf dem heap? Spricht was dagegen, das auf dem stack zu machen?
-
Helzlichen Dank für deine Mühe!
Ich werde es gleich morgen früh in dieser Art ausprobieren.Ja die Strukturen sind umständlich aufgebaut.
Aber wie gesagt, der WebService wurde extern entwickelt.
Und um den Service in einer C++ Applikation verwenden zu können, habe
ich gsoap eingesetzt. Es generiert aus der WebService-Beschreibungsdatei
C++ Code. So kam dieser Aufbau zustande.
-
Ok verstanden. Wie kann ich nun das Problem beheben, also spricht uninitialiesiert von x->y wegbekommen.
Ich kann den von gsoap-erstellte Quellcode schlecht ändern, da
sonst der Webservice nicht mehr funktioniert.Gibt es eine Möglichkeit das Problem zuheben an der Stelle
wo die Zuweisung passiert?a->incomingTests->Tests[0]->testin->id = "asdf";
-
Manuel_XY schrieb:
Ok verstanden. Wie kann ich nun das Problem beheben, also spricht uninitialiesiert von x->y wegbekommen.
Wenn du das was ich geschrieben habe, verstanden hast, dann hast du auch das Problem gelöst. 
Kann es sein, dass du einfach nur erwartest, dass dir jemand dein Programm schreibt? Falls ja: Hier gibt's dafür auch ein Projekteforum.
-
nein ich hab leider nur keinen Plan wie ich x->y initialisieren kann.
Nach meinem Verständnis sollte es die jeweiligen Instanzen nach new geben.
-
erbarme dich doch einfach

und geb mir bitte einen Tipp.
-
Das hat dir doch schon SeppJ geschrieben, also in der Form:
a->incomingTests = new ...; a->incomingTests->Tests = new ...; a->incomingTests->Tests[0] = new ...; a->incomingTests->Tests[0]->testin = new ...; a->incomingTests->Tests[0]->testin->id = "asdf";Jedoch scheint das ein eigenartiger WebService zu sein, wenn man so ein Gefrickel betreiben muß...
-
_ns1__test* a = new _ns1__test; a->incomingTests = new ns1__ArrayOfTests; a->incomingTests->Tests[0] = new ns1__Tests; a->incomingTests->Tests[0]->testin = new ns1__TestIn; a->incomingTests->Tests[0]->testin->uniqueid = "asdf";genau das habe ich heute morgen ausprobiert.
Leider bekomme ich so auch einen segfault!
-
_ns1__test* a = new _ns1__test; a->incomingTests = new ns1__ArrayOfTests; a->incomingTests->Tests = new ns1__Tests; //neu a->incomingTests->Tests[0] = new ns1__Tests; a->incomingTests->Tests[0]->testin = new ns1__TestIn; a->incomingTests->Tests[0]->testin->uniqueid = "asdf";hilft leider auch nicht
-
Eine wichtige Zeile fehlt bei dir aber... (wobei ich zugeben muß, daß ich auch ein Detail vergessen hatte):
a->incomingTests->Tests = new ns1__Tests*[1]; // Arraygröße angeben!!!Edit:
wobeins1__Tests* *Testsganz fies formatiert ist (da es sich hierbei um einen Doppelzeiger (**) handelt)!
-
Scheint zu funktionieren!
P.S. Ich liebe dich

-
Hab noch eine Frage.
Kann ich Objekte explizit auf NULL setzten?... a->incomingTests->Tests[0]->testin = new ns1__TestIn; a->incomingTests->Tests[0]->testin = NULL;Oder sind die automatisch NULL nach dem sie instanziiert wurden,
also nacha->incomingTests->Tests[0]->testin = new ns1__TestIn;