Releasing allocated memory from a class method - c++-cli

I have a c++-cli class Locator with a function Locate that takes a lot of memory while it is running. At the end of running, most of the memory is released withing the function by releasing the pointers, but there is still some memory that is not deallocated and if I run the program continuously in a lopp, it stacks up. Is there a way to completely remove all the memory that was allocated using the destructor/constructor at the end of the function each time?
public ref class Locator
{
public:
Locator() { }
~Locator() { }
Dictionary<String^, array< Byte >^>^ Locate(Dictionary<String^, String^>^ imgParms)
{ ..... }
private:
int m_HP;
int main ()
{
Locator r;
Dictionary<String^,String^>^ myDictionary = gcnew Dictionary<String^,String^>();
Dictionary<String^,List<array<Byte>^>^>^ myResult1 = gcnew Dictionary<String^,List<array<Byte>^>^>();
myResult1=r.Locate(myDictionary,0);
return 0;
}

Call delete() on the objects you create(just like plain C++). Simply dereferencing the pointer will leave the object for the garbage collector to dispose. Ordinarily this is fine, but if you use a lot of memory in your application, you dont want the wait for the GC to release memory. Ensure that your destructors delete all objects allocated by their respective destructors. This is exactly the same as plain C++. C++/CLI classes implicitly inherit the IDisposable interface and the destructors are wrappers for Dispose() so you dont have to define dispose() seprately(If i remember correctly; you can't do that anyway).

Related

How to make a Rust singleton's destructor run?

These are the ways I know of to create singletons in Rust:
#[macro_use]
extern crate lazy_static;
use std::sync::{Mutex, Once, ONCE_INIT};
#[derive(Debug)]
struct A(usize);
impl Drop for A {
fn drop(&mut self) {
// This is never executed automatically.
println!(
"Dropping {:?} - Important stuff such as release file-handles etc.",
*self
);
}
}
// ------------------ METHOD 0 -------------------
static PLAIN_OBJ: A = A(0);
// ------------------ METHOD 1 -------------------
lazy_static! {
static ref OBJ: Mutex<A> = Mutex::new(A(1));
}
// ------------------ METHOD 2 -------------------
fn get() -> &'static Mutex<A> {
static mut OBJ: *const Mutex<A> = 0 as *const Mutex<A>;
static ONCE: Once = ONCE_INIT;
ONCE.call_once(|| unsafe {
OBJ = Box::into_raw(Box::new(Mutex::new(A(2))));
});
unsafe { &*OBJ }
}
fn main() {
println!("Obj = {:?}", PLAIN_OBJ); // A(0)
println!("Obj = {:?}", *OBJ.lock().unwrap()); // A(1)
println!("Obj = {:?}", *get().lock().unwrap()); // A(2)
}
None of these call A's destructor (drop()) at program exit. This is expected behaviour for Method 2 (which is heap allocated), but I hadn't looked into the implementation of lazy_static! to know it was going to be similar.
There is no RAII here. I could achieve that behaviour of an RAII singleton in C++ (I used to code in C++ until a year a back, so most of my comparisons relate to it - I don't know many other languages) using function local statics:
A& get() {
static A obj; // thread-safe creation with C++11 guarantees
return obj;
}
This is probably allocated/created (lazily) in implementation defined area and is valid for the lifetime of the program. When the program terminates, the destructor is deterministically run. We need to avoid accessing it from destructors of other statics, but I have never run into that.
I might need to release resources and I want drop() to be run. Right now, I end up doing it manually just before program termination (towards the end of main after all threads have joined etc.).
I don't even know how to do this using lazy_static! so I have avoided using it and only go for Method 2 where I can manually destroy it at the end.
I don't want to do this; is there a way I can have such a RAII behaved singleton in Rust?
Singletons in particular, and global constructors/destructors in general, are a bane (especially in language such as C++).
I would say the main (functional) issues they cause are known respectively as static initialization (resp. destruction) order fiasco. That is, it is easy to accidentally create a dependency cycle between those globals, and even without such a cycle it is not immediately clear to compiler in which order they should be built/destroyed.
They may also cause other issues: slower start-up, accidentally shared memory, ...
In Rust, the attitude adopted has been No life before/after main. As such, attempting to get the C++ behavior is probably not going to work as expected.
You will get much greater language support if you:
drop the global aspect
drop the attempt at having a single instance
(and as a bonus, it'll be so much easier to test in parallel, too)
My recommendation, thus, is to simply stick with local variables. Instantiate it in main, pass it by value/reference down the call-stack, and not only do you avoid those tricky initialization order issue, you also get destruction.

Cannot cast pointer field while can cast same pointer defined within method in managed classes

I have unmanaged object of WtfClass.
class WtfClass { };
And I also have managed class which uses pointer to this object.
ref class MyClass //works fine if you remove "ref"
{
public:
void MyMethod();
void WtfMethod(void * pVoid);
WtfClass *pWtfStruct;
};
void MyClass::MyMethod()
{
/*WtfClass* pWtfStruct; //if you uncomment this it will compile even with ref*/
WtfMethod((int*)(&pWtfStruct)); //(!!!invalid type conversion here)
}
void MyClass::WtfMethod(void *pVoid)
{}
I can't cast WtfClass* pointer from field, but can easily cast the same pointer defined within MyMethod(). If make MyClass unmanaged it works in any case.
It's better to look at screenshots:
https://ibin.co/2iOcN1ooaC7A.png [using ref-bad.png]
https://ibin.co/2iOcYtP84H0e.png [using ref-good.png]
ibin.co/2iOcjCCc2gQe.png [without ref.png] (sorry not enough reputation to paste more than 2 links)
Of course I can have workaround like this, but I'd like to understand why this happening:
void MyClass::MyMethod()
{
WtfClass* pWorkAround = pWtfStruct; //not required in this case
WtfMethod((void*)(&pWorkAround));
}
OK, so to summarize, without the duplicate field & local variable names:
ref class MyClass
{
WtfClass* fieldWtfPtr;
void foo()
{
WtfClass* localvarWtfPtr;
WtfMethod((int*)(&fieldWtfPtr)); // Error
WtfMethod((int*)(&localvarWtfPtr)); // Works
}
};
Side question: &fieldWtfPtr is of type WtfClass**, a double pointer. Did you mean to cast that to a int**, also a double pointer? Or perhaps did you want to take fieldWtfPtr as a WtfClass* single pointer and cast that to a int* single pointer?
Here's why you're getting the error: MyClass is a managed object. The garbage compiler is allowed to move it around at any point, without telling you. So, it's location in memory can change at any point. So when you try to take the address of a class field, it's not valid because the address of that field can change at any point!
Why the other things make it work:
Local variables are stored on the stack, and the stack doesn't get moved around by the garbage collector, so it is valid to take the address of a local variable.
If you remove the ref, then MyClass is no longer a managed object, so the garbage collector won't move it around, so now the addresses of its fields won't change willy-nilly.
For this case, the easiest fix would be to make use of a local temporary variable.
void foo()
{
WtfClass* localCopyWtfPtr = this->fieldWtfPtr;
WtfMethod((int*)(&localCopyWtfPtr)); // Works
// If WtfMethod changed the data, write it back.
this->fieldWtfPtr = localCopyWtfPtr;
}
When I tried to recreate this, the compiler generated the following error:
error C2440: 'type cast' : cannot convert from 'cli::interior_ptr<CWtfClass*>' to 'LPVOID *'
I think what is going on here is some magic that allows managed classes to have unmanaged members. The MSDN documentation for cli::interior_ptr describes what's going on - basically this is used to allow for the managed object to change its memory address in the managed heap, which would cause problems when native pointers come in to play.
The reason that assigning the member to a variable first works is most likely because it has an implicit conversion to the template parameter, but since it is a managed type the compiler won't allow you to get the address of the variable (since the garbage collector can move it around in memory as needed).
The workaround in your question is probably the best way to fix this compiler error.
David answered why this happens and suggested a workaround for your case.
I'll just post a different solution here: You can pin your managed object to tell the GC not to move it around. The most lightweight way to do that is through pin_ptr (the GC won't even know you pinned something unless it stumbles upon your code in the middle of a collection). As long as it stays in scope, the managed object will be pinned and won't move. It's best if you avoid pinning for too long, but this lets you get a pointer to a chunk of managed memory which is guaranteed not to move - it's helpful when you want to avoid copying things around.
Here's how to do it:
pin_ptr<WtfClass*> pin(&pWtfStruct);
WtfMethod(pin);
pin acts just like a WtfClass**.
Regarding side question of David Yaw.
I faced with this problem while used some WINAPI functions.
IAudioEndpointVolume* pWtfVolume = NULL;
pDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, (void**)&pWtfVolume);
pWtfVolume->SetMute(BST_CHECKED, pGuidMyContext);
And it's working only if I pass &pWtfVolume. Ironically you can pass argument without "&", just pFieldVolume and compiler will say OKAY, but interface IAudioEndpointVolume will not work.
Look at this:
ref class MyClass
{
WtfClass* fieldWtfPtr;
void foo()
{
WtfClass* localvarWtfPtr;
WtfMethod((int*)(&fieldWtfPtr)); // Error
WtfMethod((int*)(&localvarWtfPtr)); // Works
WtfMethod((int*)(fieldWtfPtr)); // Compiles!!!
}
};

How can I use a 'native' pointer in a reference class in C++/CLI?

I am trying to write a small library which will use DirectShow. This library is to be utilised by a .NET application so I thought it would be best to write it in C++/CLI.
I am having trouble with this line however:
HRESULT hr = CoCreateInstance( CLSID_FilterGraph,
NULL,
CLSCTX_INPROC_SERVER,
IID_IGraphBuilder,
(void**)(&graphBuilder) ); //error C2440:
Where graphBuilder is declared:
public ref class VideoPlayer
{
public:
VideoPlayer();
void Load(String^ filename);
IGraphBuilder* graphBuilder;
};
If I am understanding this page correctly, I can use */& as usual to denote 'native' pointers to unmanaged memory in my C++/CLI library; ^ is used to denote a pointer to a managed object. However, this code produces:
error C2440: 'type cast' : cannot convert from 'cli::interior_ptr' to 'void **'
The error suggests that graphBuilder is considered to be a 'cli::interior_ptr<Type>'. That is a pointer/handle to managed memory, isn't it? But it is a pure native pointer. I am not trying to pass the pointer to a method expecting a handle or vice versa - I simply want to store it in my managed class) If so, how do I say graphBuilder is to be a 'traditional' pointer?
(This question is similar but the answer, to use a pin_ptr, I do not see helping me, as it cannot be a member of my class)
The error message is a bit cryptic, but the compiler is trying to remind you that you cannot pass a pointer to a member of a managed class to unmanaged code. That cannot work by design, disaster strikes when the garbage collector kicks in while the function is executing and moves the managed object. Invalidating the pointer to the member in the process and causing the native code to spray bytes into the gc heap at the wrong address.
The workaround is simple, just declare a local variable and pass a pointer to it instead. Variables on the stack can't be moved. Like this:
void init() {
IGraphBuilder* builder; // Local variable, okay to pass its address
HRESULT hr = CoCreateInstance(CLSID_FilterGraph,
NULL,
CLSCTX_INPROC_SERVER,
IID_IGraphBuilder,
(void**)(&builder) );
if (SUCCEEDED(hr)) {
graphBuilder = builder;
// etc...
}
}

gcroot in c++/cli

What does gcroot mean? I found it in code I am reading.
gcroot is a C++/cli template class that eases holding managed types in C++/cli classes.
You can for example have the following:
#include <msclr/gcroot.h>
using namespace msclr;
class Native {
public:
Native(Object ^obj) :
netstring(obj->ToString()) { // Initializing the gcroot<String ^>
}
~Native() {
}
void Print() {
array<Char> ^chars = netstring->GetChars(); // Dereferencing the gcroot<String ^>
_wprintf("netstring is:");
if (chars->Length > 0) {
pin_ptr<Char> charptr = &(chars[0]);
_wprintf("%s", (wchar_t const *)charptr);
}
}
private:
gcroot<String ^> netstring;
};
gcroot acts as a reference to the managed object or value type instance and is doing all the work when copying the object or value type instance.
Normally you need to work with GCHandle and some C functions of the .NET framework. This is all encapsulated in gcroot.
When the .NET garbage collector runs, it determines which objects are still in use by doing reachability analysis. Only the managed heap is analyzed while looking for pointers to objects, so if you have a pointer from a native object to a managed object, you need to let the garbage collector know, so it can include it in reachability analysis, and so it can update the pointer if the target moves during compaction.
As rstevens said, the .NET GCHandle class does this, and C++/CLI is a C++-oriented wrapper for GCHandle which adds type safety and convenient syntax.

C++ Ref class not a member of System::IDisposable; trouble implementing IDisposable

I want to make a global vector of my own object class called "Person". However, the compiler says that
error C2039: '{dtor}' : is not a member of 'System::IDisposable'
1> c:\windows\microsoft.net\framework\v2.0.50727\mscorlib.dll : see declaration of 'System::IDisposable'
So I looked up how to implement IDisposable (which I now know is used primarily for unmanaged resources) but still can't seem to implement it with the following:
ref class Globals : System::IDisposable
{
public:
static cliext::vector<Person^> person_data = gcnew cliext::vector<Person^>;
void Dispose()
{
delete person_data;
}
};
The 2 errors I get are:
error C2605: 'Dispose' : this method is reserved within a managed class
1> did you intend to define a destructor?
error C3766: 'Globals' must provide an implementation for the interface method 'void System::IDisposable::Dispose(void)'
1> c:\windows\microsoft.net\framework\v2.0.50727\mscorlib.dll : see declaration of 'System::IDisposable::Dispose'
You don't have to explicitly derive from IDisposable. Following the MSDN doco, use the following pattern:
ref class Globals
{
public:
static cliext::vector<Person^> person_data = gcnew cliext::vector<Person^>;
!Globals() // finalizer
{
delete person_data;
{
protected:
~Globals() // destructor calls finalizer
{
this->!Globals();
}
};
Use a destructor. In C++/CLI ~ClassName() is Dispose() and !ClassName() is equivalent to C#'s ~ClassName(). In your case:
ref class Globals : System::IDisposable
{
public:
static cliext::vector<Person^> person_data = gcnew cliext::vector<Person^>;
void ~Globals()
{
delete person_data;
}
};
use a finalizer as shown at http://www.codeproject.com/KB/mcpp/cppclidtors.aspx
You don't need to implement Dispose() yourself, either directly or via a destructor. The implicitly-generated destructor already destroys all member objects. The IDisposable interface will be added automatically, don't mention it explicitly.
Next, you need to make up your mind whether person_data is a handle (which has to be set to an instance created with gcnew) or member object semantics (like stack semantics, the constructor is automatically called by the constructor of the parent object, the destructor called automatically when the lifetime of the parent object ends, and you use "." instead of "->" to access members).
Also, are you sure you want one copy of person_data shared between all instances of "Globals", but destroyed by the first instance to be disposed, leaving any other instances holding an invalid reference (reference to disposed object)? It looks like you're trying to use a Singleton anti-pattern here, is that correct?
From C++/CLI in Action The C++/CLI Dispose pattern has these rules (paraphrased):
If a class has a finalizer or a
destructor the compiler generates
Dispose(bool) that will call either
the finalizer or destructor based on
the bool value.
If it has just a d'tor (~type) then the compiler calls
Dispose(true) so the d'tor is called.
If it has just a finalizer (!type)
then the compiler calls
Dispose(false) so the finalizer is
called
Also for the second rule: The compiler will implement the IDisposable interface for you (by generating Dispose()). It then uses SuppressFinalize to make sure the finalizer isn't called.
I did this to your code and the only way I could get it to compile was to make person_data a instance member. The error i got when it was static was error C2039: '{dtor}' : is not a member of 'System::IDisposable' which doesn't make much sense.
Also, do you even need to delete the person_data vector since is a managed object? Maybe you do but I haven't used the cliext enough to say.
Edit Perhaps the first paragraph of this article has the answer (emphasis mine):
When you declare a member variable as
static and when the application
starts, the compiler creates a copy of
that member. This member would be
maintained by the compiler while the
program is running. If you declare an
instance of a class, like the above
vehicle variable, the static member is
not part of the object: the compiler
creates and maintains the static
member, whether you use it or not,
whether you declare a class variable
or not.