[erledigt] Speicher allokieren in C++/CLI
-
Hallo,
ich habe gerade ein Verständnisproblem mit dem Aufruf einer normalen C-Funktion. Der Prototyp sieht folgendermasen aus:
int Tcl_LinkVar(Tcl_Interp *interp, const char *varName, char *addr, enum type)Es handelt sich um eine Funktion, die in einem Tcl-Interpreter C-Variablen mit Tcl-Variablen verbindet. Man sollte dabei den Speicher für char *addr mit malloc allokieren, damit der Interpreter bei Änderung der Variablen mit free den Speicher freigeben kann und mit alloc auf einen neuen Speicher zeigen kann, der dann einen neuen String repräsentiert.
Jetzt bin ich mir nicht sicher, ob man überhaupt noch mit malloc arbeiten soll. Es wird ja Speicher reserviert, aber wärend der Interpreter läuft, könnte der GC den Speicher umschichten und der Zeiger zeigt auf einmal ins Nirwana.
Mit einem pin_ptr<char> könnte man dafür sorgen, dass das nicht passieren kann, aber leider bekomme ich dann zur Laufzeit die Fehlermeldung :
Eine nicht behandelte Ausnahme des Typs "System.AccessViolationException" ist in SETclClr.dll aufgetreten.
Zusätzliche Informationen: Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist.
Wie behandle ich am besten so ein Problem?
-
Ich seh schon, diese Konzepte wie
pin_ptrusw. bereiten dir einiges an Kopfzerbrechen. Grundsätzlich gilt bei C++/CLI, dass du alles so machen kannst, wie es verlangt wird - und deshalb solltest du auch so machen. Sprich: Wenn Speicher mittelsmallocallokiert werden soll, dann machst du das bitte auch. Die Verwendung einespin_ptrin Kombination mit einemarrayzur Allokation von Speicher mittelsgcnewist nicht nur unnötig kompliziert, sondern ergibt auch keinerlei Sinn wenn er schlussendlich ja wieder mitfreefreigegeben wird. Die Freigabe von nicht richtig allokiertem Speicher, wie es bei dir irgendwo passiert resultiert vermutlich in deinerAccessViolationException(...die du auch nur wegen .NET zu sehen bekommst. Ohne die Runtime würden dir wohl einige andere Dinge um die Ohren fliegen, undefiniertes Verhalten ;)).Ganz abgsehen davon darfst du eben genau in diesem Fall keinen
pin_ptrbenutzen. Ich habe keine Ahnung wieTcl_LinkVarintern funktioniert, aber ich gehe davon aus das intern einer nativer Zeiger auf deinen Speicher gespeichert wird. Nach dem Aufruf dieser Funktion wird der von dir übergebenepin_ptraber eventuell ungültig, dein Zeiger zeigt ins Nichts, weil das Scope verlassen wird und der Destruktor vonpin_ptraufgerufen wird. Infolgedessen darf der GC deinen Speicher verschieben. Du könntest versuchen, deinenpin_ptram Leben zu erhalten solange Tcl läuft. In Anbetracht der Alternativen ist das jedoch alles andere als sinnvoll...So drop it & allokier den Speicher wie immer per
mallocund gut ist
-
Vergiss pin_ptr in diesem Zusammenhang... Programmiere einfach so wie _ohne_ C++/CLI und konvertiere die Strings entsprechend!
Siehe:
http://www.c-plusplus.net/forum/viewtopic-var-t-is-158664.html
http://www.c-plusplus.net/forum/viewtopic-var-t-is-158666.html
-
Der Code sieht im Moment so aus:
char *cPtr; char szVarName[] = "source_0"; cPtr = Tcl_Alloc(80); Tcl_LinkVar(interp, szVarName, cPtr, TCL_LINK_STRING);Statt Tcl_Alloc(80) habe ich auch malloc(80) ausprobiert. Beides führt bei Aufruf von Tcl_LinkVar(...) zu bekannter Fehlermeldung:
Eine nicht behandelte Ausnahme des Typs "System.AccessViolationException" ist in SETclClr.dll aufgetreten.
Zusätzliche Informationen: Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist.
Ich bin der Meinung, dass ich es richtig gemacht habe. Diese Fehlermeldung war der Grund, warum ich auf die Idee gekommen bin, pin_ptr<char> zu verwenden. Dann kam die Fehlermeldung nicht mehr, geklappt hat das ganze aber auch nicht. Nach Ablauf des Tcl-Skripts stand nur Undefiniertes drin, bzw. bei Aufruf des Skripts kam ein Laufzeitfehler wegen beschädigtem Speicher (oder so ähnlich).
-
Hat sich erledigt. Das Problem lag in der Funktion.
Der Aufruf muss heißen:char *cPtr; char szVarName[] = "source_0"; cPtr = Tcl_Alloc(80); Tcl_LinkVar(interp, szVarName, (char *)&cPtr, TCL_LINK_STRING);In der Funktion wird neuer Speicher allokiert und deshalb kann sich der Pointer ändern.