Zeiger "vernichtet" sich selbst?
-
Einen wunderschönen guten Morgen zusammen
,
vorneweg: es kann gut sein, das dieses Problem recht trivial ist und es hier schon einige Lösungen gibt - ich habe keine gefunden, also bitte nicht haun wenn das schon der 15. Beitrag von dieser Sorte ist.
Mein Code sieht (stark vereinfacht) so aus:
public ref class MyClass { private: MyExternalClass *pointer; public: MyClass() { pointer = createMyExternalClass(); } void foo() { pointer->bar(); } };
Die Klasse besitzt weder Finalisierer noch Destruktor noch ein Dispose.
MyExternalClass ist eine abstrakte Klasse von der mittels createMyExternalClass() eine Instanz erzeugt werden kann (beides natives C++).Folgender Code führt in Zeile 2 zu einer NullReferenceException:
MyClass^ c = gcnew MyClass(); c->foo();
Nach dem Ablauf des Konstruktors wird pointer auf null gesetzt - obwohl der Zeiger ja ohne GC erzeugt wurde und keine Methode meiner Klasse das tun würde.
Ich hoffe einer von euch weiß da Rat - Ich bin zwar C# und C++-Veteran, aber bei C++/CLI absoluter Newbie.
Danke!
trion
-
Hab gerade mal auf die schnelle das hier getestet, geht ohne Probleme.
Bist du sicher, dass das Problem nicht irgendwo anders liegt ?
#include "stdafx.h" using namespace System; class UnmanagedBase { public: virtual ~UnmanagedBase() {} virtual int foo() = 0; }; class UnmanagedImp : public UnmanagedBase { private: int m_n; public: UnmanagedImp() { m_n = 42; } int foo() { return m_n; } }; public ref class Managed { private: UnmanagedBase *m_pUnmanaged; public: Managed() { m_pUnmanaged = new UnmanagedImp; } ~Managed() { delete m_pUnmanaged; } int foo() { return m_pUnmanaged->foo(); } }; int main(array<System::String ^> ^args) { Managed ^m = gcnew Managed; Console::WriteLine(m->foo().ToString()); return 0; }
-
Danke für die Antwort.
Stimmt, du hast recht, das Problem war wirklich woanders:
Der Konstruktor ist überladen und ich hab die Überladung aufgerufen, die den ersten Konstruktor aufruft - der äußere killt dann den Zeiger, weil er ihn initialisiern will.Ich dachte das funktioniert so:
MyClass(int arg1, int arg2, int arg3, int arg4) { foo(arg1, arg2, arg3, arg4); } MyClass(int arg1, int arg2) { MyClass(arg1, arg2, 1337, 42); }
Gibt es eine Möglichkeit, das so umzuschreiben, dass der äußere Konstruktor die Variablen nicht "nochmal" initialisiert?
-
Ja, initialisierungs code auslagern (z.B. void init()) und dann in den jeweiligen konstruktoren init() aufrufen.
Simon
-
Ich hatte zwar gehofft das geht eleganter, aber nun werde ich das wohl so machen.
Danke!
-
Ich kenne mich mit C++/CLI nicht wirklich aus, aber in C# gibt es folgende Möglichkeit:
MyClass(int arg1, int arg2, int arg3, int arg4) { foo(arg1, arg2, arg3, arg4); } MyClass(int arg1, int arg2) : this(arg1, arg2, 1337, 42) { }
Vielleicht gibt es ja etwas Ähnliches in C++/CLI.