Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Managed class with a non-managed member

Tags:

c++

clr

I'm using this class:

public ref class x: public System::Windows::Forms::Form
{ 
     private: gcroot<std::string> name;
}

and i am getting the following error:

IntelliSense: a member of a managed class cannot be of a non-managed class type

I know i can use char*, but if I use lots of char* i will have to manually do the delete[] or some heap corruption issues will rise

I've been stuck on this for two days now

note: I have to use c++ and have to use UI in c++

like image 822
HalaKuwatly Avatar asked Nov 24 '13 09:11

HalaKuwatly


1 Answers

That's the wrong usage for gcroot<>, you only need that if you keep a reference to a managed object in an unmanaged class.

In this case you only need to declare it string*. A pointer, you cannot store an string object inside your managed class, the compiler is convinced that you are going to shoot your leg off. You'll get the exact same error message you got now.

Really Bad Things can happen when the garbage collector compacts the gc heap and moves the Form object. That invalidates any external unmanaged pointer to the string object without the garbage collector being able to update that pointer. Such a pointer can for example be generated when you pass a reference to the string to unmanaged code and the GC happens while that unmanaged code is executing. The pointer is now no longer valid and the unmanaged code fails when it reads garbage or corrupts the GC heap. Especially the latter mishap is extremely hard to diagnose. Just calling one of the std::string member methods is enough to invoke this failure mode, that generates the this pointer.

It is very unusual to actually need an std::string in a managed object, you always choose String^ first. And generate the std::string only when needed, typically when you call native code. Only ever consider doing it your way if creating the std::string on-the-fly is exceedingly expensive. If you do then create the std::string object in the constructor. And destroy it again in both the destructor and the finalizer. Which is pretty tricky to get right for the Form class since it already has a destructor and finalizer, strongly consider creating a little helper class that stores the string.

like image 145
Hans Passant Avatar answered Oct 20 '22 07:10

Hans Passant