Writing memleak-free code in C++ isn't a problem for me, I just keep to the RAII idiom.
Writing memleak-free code in C# isn't very hard either, the garbage collector will handle it.
Unfortunately, writing C++/CLI code is a problem for me. I thought I had understood how it works, but I still have big problems and I hope you can give me some hints.
This is what I have:
A Windows service written in C# that uses C++ libraries (for example OpenCV) internally. The C++ classes are accessed with C++/CLI wrapper classes.
For example I have a MatW C++/CLI wrapper class for a cv::Mat image object, which takes as constructor argument a System::Drawing::Bitmap:
public ref class MatW
{
public:
MatW(System::Drawing::Bitmap ^bmpimg)
{
cv::Size imgsize(bmpimg->Width, bmpimg->Height);
nativeMat = new Mat(imgsize, CV_8UC3);
// code to copy data from Bitmap to Mat
// ...
}
~MatW()
{
delete nativeMat;
}
cv::Mat* ptr() { return nativeMat; }
private:
cv::Mat *nativeMat;
};
Another C++ class might be for example
class PeopleDetector
{
public:
void detect(const cv::Mat &img, std::vector<std::string> &people);
}
And its wrapper class:
public ref class PeopleDetectorW
{
public:
PeopleDetectorW() { nativePeopleDetector = new PeopleDetector(); }
~PeopleDetectorW() { delete nativePeopleDetector; }
System::Collections::Generic::List<System::String^>^ detect(MatW^ img)
{
std::vector<std::string> people;
nativePeopleDetector->detect(*img->ptr(), people);
System::Collections::Generic::List<System::String^>^ peopleList = gcnew System::Collections::Generic::List<System::String^>();
for (std::vector<std::string>::iterator it = people.begin(); it != people.end(); ++it)
{
System::String^ p = gcnew System::String(it->c_str());
peopleList->Add(p);
}
return peopleList;
}
And here is the call to the method in my Windows Service C# class:
Bitmap bmpimg = ...
using (MatW img = new MatW(bmpimg))
{
using (PeopleDetectorW peopleDetector = new PeopleDetector())
{
List<string> people = peopleDetector.detect(img);
}
}
Now, here's my questions:
is there anything wrong with my code?
do I have to use using in my C# code? It makes the code ugly, when there are multiple wrapper objects in use, because the using statements have to be nested
could I use Dispose() instead after having used the objects?
Could I just not bother and leave it to the garbage collector?
(no using, no Dispose())
is the above code the right way to return objects like List<string^>^ from C++/CLI to C#?
does using gcnew not mean that the garbage collector will take care of the objects and I don't have to care how and when to free them?
I know that's a lot of questions, but all I want is to get rid of my memory leak, so I listed everything that I think could possibly go wrong...
is there anything wrong with my code?
Not in what you've posted - you are applying using statements correctly. So your code sample is not the cause of your memory leaks.
do I have to use using in my C# code? It makes the code ugly, when there are multiple wrapper objects in use, because the using statements have to be nested
You don't have to, but you don't have to nest them syntactically. This is equivalent:
Bitmap bmpimg = ...
using (MatW img = new MatW(bmpimg))
using (PeopleDetectorW peopleDetector = new PeopleDetector())
{
List<string> people = peopleDetector.detect(img);
}
could I use Dispose() instead after having used the objects?
You could, but then you'll need a try/finally to ensure Dispose is always called, even when an exception is thrown. The using statement encapsulates that whole pattern.
Could I just not bother and leave it to the garbage collector? (no using, no Dispose())
C++ RAII is commonly applied to all kinds of temporary state clean-up, including things like decrementing a counter that was incremented in the constructor, etc. Whereas the GC runs in a background thread. It is not suitable for all the deterministic clean-up scenarios that RAII can take care of. The CLR equivalent of RAII is IDisposable, and the C# language interface to it is using. In C++, the language interface to it is (naturally) destructors (which become Dispose methods) and the delete operator (which becomes a call to Dispose). Ref class objects declared "on the stack" are really just equivalent to the C# using pattern.
is the above code the right way to return objects like List^ from C++/CLI to C#?
Pretty much!
does using gcnew not mean that the garbage collector will take care of the objects and I don't have to care how and when to free them?
You don't have to free the memory. But if the class implements IDisposable, then that is a totally separate issue from memory allocation. You have to call Dispose manually before you abandon the object.
Be wary of finalizers - these are a way of hooking into the GC to get your own clean-up code to run when the GC collects your objects. But they are not really fit for general use in application code. They run from a thread that you don't control, at a time you don't control, and in an order that you don't control. So if one object's finalizer tries to access another object with a finalizer, the second object may already have been finalized. There is no way to control the ordering of these events. Most of the original uses of finalizers are nowadays covered by SafeHandle.
You don't have a finalizer in the ref class.
In C++/CLI the destructors are called either when you create an instance of the class on the stack (C++ style) and then it goes out of scope, or you use the delete operator.
The finalizers are called by the GC when it's time to finalize the object.
In C# the GC handles the destruction of all the objects (there's no delete operator) so there's no distinction between the destructor and finalizer.
So the "destructors" with the ~ behave like c++ destructors, not at all like C# destructors.
The "destructors" in C++/CLI ref class are compiled into a .Net Dispose() method.
The equivilant to a C# destructor/finalizer is the finalizer method witch is defined with a ! (exclamation mark).
So, to avoid memory leaks, you need to define a finalizer:
!MatW()
{
delete nativeMat;
}
~MatW()
{
this->!MatW();
}
See the MSDN article Destructors and Finalizers in visual C++
Use the
Related
This question already has answers here:
What is IDisposable for?
(6 answers)
Closed 7 years ago.
I come from a C++ background and have trouble understanding the point of IDisposable objects (and the point of many other things in .NET). Why is a Dispose function necessary in the first place? Whatever it does, why not do that in the destructor of the class? I understand it cleans up managed resources, but isn't that what a destructor is supposed to do? I understand that
Using ( var obj = new SomeIDisposableObject )
{
// ...
}
is the equivalent of
var obj = new SomeIDisposableObject;
// ...
obj.Dispose();
but how does that save any typing? And if C# has a garbage collector, which it does, then why are we ever worried about disposing resources?
Is IDisposable/Using/etc. a Skeet-approved concept? What does he think of it?
IDisposable is nothing special. It's just an interface that makes you have a Dispose() function. IDisposable won't clear anything or destroy objects. A call to Dispose() does nothing if that function does nothing.
The use of IDisposable is a pattern. It's so important that it gets its own language construct (the using block), but it's just a pattern.
The difference with a destructor, is that in .NET, the destructor is non-deterministic. You never know when the garbage collector will collect your object. You don't even know if it even will (unlike using delete in C++, which is deterministic).
So IDisposable is there for deterministically releasing unneeded references (and releasing unmanaged resources). The "disposed" object will remain in memory after you call Dispose until the garbage collector decides to collect it (at which point, the "destructor" will be called, unless you explicitly tell it not-to), if it ever decides to.
That's the main difference to using "destructors" (or finalizers, as they are called in C#).
As for the why do we need it:
Managed references to other objects prevent objects to be collected by the garbage collector. So you need to "release" those references (by, for example, setting the variables that reference those objects to null).
Objects in .NET can use unmanaged resources, if they use native libraries. For example, every control or bitmap in a Windows.Forms application uses a Win32 handler, which is unmanaged. If you don't release those resources, you may reach the handle limit in Windows if using any big application, easily. Also, if you need interoperability with any non-.NET API, you'll more likely have to allocate unmanaged memory (with the use of, for example, Marshal.AllocHGlobal), which will need to be released at some point: that point is generally the Dispose() function of the IDisposable, which must be called explicitly (or by using a using block).
As for the using block, it's more equivalent to:
var myObject = new MyDisposableClass();
try
{
...
}
finally {
myObject.Dispose();
}
So it does indeed save typing
Using a using block doesn't only call the .Dispose method; it calls the .Dispose method when you leave the block, however you leave it. So, if your code crashes, it will still call Dispose. The actual code would be closer to:
try
{
var obj = new SomeIDisposableObject;
// ...
}
catch (exception ex)
{
}
finally
{
obj.Dispose();
}
Additionally, destructors don't always fire when you expect them to. I've had a few bugs where the destructor is called after the program has apparently exited, and tried to access resources that no longer exist. Since you don't know when it will be called, it's difficult to fix this.
I have an assembly in 'C++/CLI' which implements certain classes. Let us assume the class is of 'SomeType'.
Now, in an application developed in 'C#', to do the following -
while(!Console.KeyAvailable)
{
using(SomeType type = new SomeType())
{
type.doSomething(); //do something
}
}
Would it have any consequence, like memory leaks etc. in any situation, say if there was an unhandled exception or any such?
I read that the using keyword should generally be used for a class which implements IDisposable, but for a C++/CLI class?
C++/CLI does not have an equivalent of the using keyword. It took a different approach, one that native C++ programmers expect. Who are familiar with a very common C++ idiom to implement deterministic destruction, the RAII pattern. Invoking it requires using "stack semantics". Works well, the syntax requirements are however pretty obscure.
I'll first show the clumsy way, helpful to demonstrate the syntax differences. Lets use StreamReader, a disposable class in .NET:
String^ ReadTopLineFromFile(String^ path) {
StreamReader^ reader = gcnew StreamReader(path);
try {
return reader->ReadLine();
}
finally {
delete reader;
}
}
The try/finally is what makes code exception-safe, if the ReadLine() throws an exception then the StreamReader object is still disposed and the lock on the file is guaranteed to be released. This is code that the C# compiler emits automatically when you use the using statement. Also note the use of the delete operator, it in effect calls the StreamReader::Dispose() method. The compiler won't let you write reader->Dispose(), using the operator is mandatory.
Now the using version that the C++/CLI compiler supports. You invoke stack semantics by emulating the way the native C++ compiler treats a C++ object that's allocated on the stack. Like this:
String^ ReadTopLineFromFile(String^ path) {
StreamReader reader(path);
return reader.ReadLine();
} // <== disposed here
Note the missing ^ hat on the variable name, normally required when it stores a reference type reference. Intentionally omitting it is what invokes the pattern. No explicit gcnew call required, the compiler emits it automatically. Also note that you no longer use -> to dereference the object, you now use .
The C++/CLI compiler automatically generates the try/finally blocks as well as the delete operator call. Which is emitted at the closing brace of the scope block. Just like the native C++ compiler does it. While it looks like the managed object is allocated on the stack, that's just an syntactical illusion, it is still on the GC heap.
Syntax is very different of course, the only real hangup with the feature. Knowing when to use the ^ hat and when to rely on stack semantics is something that needs to be learned, takes a while.
I come from a managed world and c++ automatic memory management is quite unclear to me
If I understand correctly, I encapsulate a pointer within a stack object and when auto_ptr becomes out of scope, it automatically calls delete on the pointed object?
What kind of usage should I make of it and how should I naturally avoid inherent c++ problems?
auto_ptr is the simplest implementation of RAII in C++. Your understanding is correct, whenever its destructor is called, the underlying pointer gets deleted.
This is a one step up from C where you don't have destructors and any meaningful RAII is impossible.
A next step up towards automagic memory management is shared_ptr. It uses reference counting to keep track of whether or not the object is alive. This allows the programmer to create the objects a bit more freely, but still not as powerful as the garbage collection in Java and C#. One example where this method fails is circular references. If A has a ref counted pointer to B and B has a ref counted pointer to A, they will never get destructed, even though no other object is using either.
Modern object orianted languages use some sort of variation of mark and sweep. This technique allows managing circular references and is reliable enough for most programming tasks.
Yes, std::auto_ptr calls delete on its content when it goes out of scope. You use auto_ptr only if no shared ownership takes place.
auto_ptr isn't particularly flexible, you can't use it with objects created with new[] or anything else.
Shared ownership is usually approached with shared pointers, which e.g. boost has implementations of. The most common usage, implemented e.g. in Boosts shared_ptr, employs a reference counting scheme and cleans up the pointee when the last smart pointer goes out of scope.
shared_ptr has one big advantage - it lets you specify custom deleters. With that you can basically put every kind of resource in it and just have to specify what deleter it should use.
Here's how you use a smart pointer. For the sake of example, I'll be using a shared_ptr.
{
shared_ptr<Foo> foo(new Foo);
// do things with foo
}
// foo's value is released here
Pretty much all smart pointers aim to achieve something similar to the above, in that the object being held in the smart pointer gets released at the end of the smart pointer's scope. However, there are three types of smart pointers that are widely used, and they have very different semantics on how ownership is handled:
shared_ptr uses "shared ownership": the shared_ptr can be held by more than one scope/object, and they all own a reference to the object. When the last reference falls off, the object is deleted. This is done using reference counting.
auto_ptr uses "transferable ownership": the auto_ptr's value can be held only in one place, and each time the auto_ptr is assigned, the assignee receives ownership of the object, and the assigner loses its reference to the object. If an auto_ptr's scope is exited without the object being transferred to another auto_ptr, the object is deleted. Since there is only one owner of the object at a time, no reference counting is needed.
unique_ptr/scoped_ptr uses "nontransferable ownership": the object is held only at the place it's created, and cannot be transferred elsewhere. When the program leaves the scope where the unique_ptr is created, the object is deleted, no questions asked.
It's a lot to take in, I'll grant, but I hope it'll all sink in soon. Hope it helps!
You should use boost::shared_ptr instead of std::auto_ptr.
auto_ptr and shared_ptr simply keep an instance of the pointer and because they are local stack objects they get deallocated when they go out of scope. Once they are deallocated they call delete on internal pointer.
Simple example, the actuall shared_ptr and auto_ptr are more sophisticated (they have methods for assignment and conversion/access to internal pointer):
template <typename T>
struct myshrdptr
{
T * t;
myshrdptr(T * p) : t(p) {}
~myshrdptr()
{
cout << "myshrdptr deallocated" << endl;
delete t;
}
T * operator->() { return t; }
};
struct AB
{
void dump() { cout << "AB" << endl; }
};
void testShrdptr()
{
myshrdptr<AB> ab(new AB());
ab->dump();
// ab out of scope destructor called
// which calls delete on the internal pointer
// which deletes the AB object
}
From somewhere else:
int main()
{
testShrdptr();
cout << "done ..." << endl;
}
output something like (you can see that the destructor is called):
AB
myshrdptr deallocated
done ...
Rather than trying to understand auto_ptr and its relation to garbage-collected references, you should really try to see the underlying pattern:
In C++, all local objects have their destructors called when they go out of scope. This can be harnessed to clean up memory. For example, we could write a class which, in its constructor, is given a pointer to heap-allocated memory, and in its destructor, frees this pointer.
That is pretty much what auto_ptr does. (Unfortunately, auto_ptr also has some notoriously quirky semantics for assignment and copying)
It's also what boost::shared_ptr or other smart pointers do. There's no magic to any of those. They are simply classes that are given a pointer in their constructor, and, as they're typically allocated on the stack themselves, they'll automatically go out of scope at some point, and so their destructor is called, which can delete the pointer you originally passed to the constructor. You can write such classes yourself. Again, no magic, just a straightforward application of C++'s lifetime rules: When a local object goes out of scope, its destructor is called.
Many other classes cut out the middleman and simply let the same class do both allocation and deallocation. For example, std::vector calls new as necessary to create its internal array -- and in its destructor, it calls delete to release it.
When the vector is copied, it takes care to allocate a new array, and copy the contents from the original one, so that each object ends up with its own private array.
auto_ptr, or smart pointers in general, aren't the holy grail. They don't "solve" the problem of memory management. They are one useful part of the recipe, but to avoid memory management bugs and headaches, you need to understand the underlying pattern (commonly known as RAII) -- that is, whenever you have a resource allocation, it should be tied to a local variable which is given responsibility for also cleaning it up.
Sometimes, this means calling new yourself to allocate memory, and then passing the result to an auto_ptr, but more often, it means not calling new in the first place -- simply create the object you need on the stack, and let it call new as required internally. Or perhaps, it doesn't even need to call new internally. The trick to memory management is really to just rely on local stack-allocated objects instead of heap allocations. Don't use new by default.
Choose an imperative language (such as C, C++, or ADA) that provides pointer types.
Redesign that language to abolish pointer types, instead allowing programmers to define recursive types directly.
Consider carefully the issue of copy semantics vs reference semantics. Implement an interpreter for the language using DrRacket .
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What does the tilde (~) mean in C#?
class ResourceWrapper
{
int handle = 0;
public ResourceWrapper()
{
handle = GetWindowsResource();
}
~ResourceWrapper() //this line here
{
FreeWindowsResource(handle);
handle = 0;
}
[DllImport("dll.dll")]
static extern int GetWindowsResource();
[DllImport("dll.dll")]
static extern void FreeWindowsResource(int handle);
}
What does the tilde do on the line indicated.
I thought that it was the bitwise NOT operator, infact I don't really understand that whole block there, (the commented line and the parentheses blovk after it), it isn't a methd, or a parameter or anything, what is it and why is there a tilde before it?
That is destructor. It takes care that all resources are released upon garbage collection.
This implements the finalizer (the Finalize method) of the class.
Normally you should not implement a finalizer.
E.g. do this for classes that hold external unmanaged resources but be sure to implement the IDisposable Pattern in this case too.
Like in C++, ~ClassName is the destructor method. It gets called in C# when the object in question gets cleaned up by the garbage collector. Unlike in C++ where there are deterministic times when the destructor is called, there is no way of predicting when it will be called (or even if it will be called) in C#.
What you are probably looking for is the IDisposable pattern, which provides a much better approach to this.
That is a Destructor. It gives you implicit control over releasing resources. That is, it is called by the Garbage Collector. If you want explicit control over the release of resources, you can implement IDisposable Check out Implementing Finalize and Dispose to Clean Up Unmanaged Resources. The Framework Design Guidelines also has more information.
Ack, i just found the answer and can't see how to delete my question. it specifies the destructor of the class
i have no clue about C#, but from what the code does, this looks like a deconstructor, saying
free the resource referenced by handle
set handle to 0 to be sure
would kind of go together with the notion of "not" as well ... :)
i may be wrong though ...
greetz
back2dos
I am fascinated by the way the CLR and GC works (I'm working on expanding my knowledge on this by reading CLR via C#, Jon Skeet's books/posts, and more).
Anyway, what is the difference between saying:
MyClass myclass = new MyClass();
myclass = null;
Or, by making MyClass implement IDisposable and a destructor and calling Dispose()?
Also, if I have a code block with a using statement (eg below), if I step through the code and exit the using block, is the object disposed of then or when a garbage collection occurs? What would happen if I call Dispose() in the using block anyay?
using (MyDisposableObj mydispobj = new MyDisposableObj())
{
}
Stream classes (eg BinaryWriter) have a Finalize method? Why would I want to use that?
It's important to separate disposal from garbage collection. They are completely separate things, with one point in common which I'll come to in a minute.
Dispose, garbage collection and finalization
When you write a using statement, it's simply syntactic sugar for a try/finally block so that Dispose is called even if the code in the body of the using statement throws an exception. It doesn't mean that the object is garbage collected at the end of the block.
Disposal is about unmanaged resources (non-memory resources). These could be UI handles, network connections, file handles etc. These are limited resources, so you generally want to release them as soon as you can. You should implement IDisposable whenever your type "owns" an unmanaged resource, either directly (usually via an IntPtr) or indirectly (e.g. via a Stream, a SqlConnection etc).
Garbage collection itself is only about memory - with one little twist. The garbage collector is able to find objects which can no longer be referenced, and free them. It doesn't look for garbage all the time though - only when it detects that it needs to (e.g. if one "generation" of the heap runs out of memory).
The twist is finalization. The garbage collector keeps a list of objects which are no longer reachable, but which have a finalizer (written as ~Foo() in C#, somewhat confusingly - they're nothing like C++ destructors). It runs the finalizers on these objects, just in case they need to do extra cleanup before their memory is freed.
Finalizers are almost always used to clean up resources in the case where the user of the type has forgotten to dispose of it in an orderly manner. So if you open a FileStream but forget to call Dispose or Close, the finalizer will eventually release the underlying file handle for you. In a well-written program, finalizers should almost never fire in my opinion.
Setting a variable to null
One small point on setting a variable to null - this is almost never required for the sake of garbage collection. You might sometimes want to do it if it's a member variable, although in my experience it's rare for "part" of an object to no longer be needed. When it's a local variable, the JIT is usually smart enough (in release mode) to know when you're not going to use a reference again. For example:
StringBuilder sb = new StringBuilder();
sb.Append("Foo");
string x = sb.ToString();
// The string and StringBuilder are already eligible
// for garbage collection here!
int y = 10;
DoSomething(y);
// These aren't helping at all!
x = null;
sb = null;
// Assume that x and sb aren't used here
The one time where it may be worth setting a local variable to null is when you're in a loop, and some branches of the loop need to use the variable but you know you've reached a point at which you don't. For example:
SomeObject foo = new SomeObject();
for (int i=0; i < 100000; i++)
{
if (i == 5)
{
foo.DoSomething();
// We're not going to need it again, but the JIT
// wouldn't spot that
foo = null;
}
else
{
// Some other code
}
}
Implementing IDisposable/finalizers
So, should your own types implement finalizers? Almost certainly not. If you only indirectly hold unmanaged resources (e.g. you've got a FileStream as a member variable) then adding your own finalizer won't help: the stream will almost certainly be eligible for garbage collection when your object is, so you can just rely on FileStream having a finalizer (if necessary - it may refer to something else, etc). If you want to hold an unmanaged resource "nearly" directly, SafeHandle is your friend - it takes a bit of time to get going with, but it means you'll almost never need to write a finalizer again. You should usually only need a finalizer if you have a really direct handle on a resource (an IntPtr) and you should look to move to SafeHandle as soon as you can. (There are two links there - read both, ideally.)
Joe Duffy has a very long set of guidelines around finalizers and IDisposable (co-written with lots of smart folk) which are worth reading. It's worth being aware that if you seal your classes, it makes life a lot easier: the pattern of overriding Dispose to call a new virtual Dispose(bool) method etc is only relevant when your class is designed for inheritance.
This has been a bit of a ramble, but please ask for clarification where you'd like some :)
When you dispose an object, the resources are freed. When you assign null to a variable, you're just changing a reference.
myclass = null;
After you execute this, the object myclass was referring to still exists, and will continue to until the GC gets around to cleaning it up. If Dispose is explicitly called, or it's in a using block, any resources will be freed as soon as possible.
The two operations don't have much to do with each others.
When you set a reference to null, it simply does that. It doesn't in itself affect the class that was referenced at all.
Your variable simply no longer points to the object it used to, but the object itself is unchanged.
When you call Dispose(), it's a method call on the object itself. Whatever the Dispose method does, is now done on the object. But this doesn't affect your reference to the object.
The only area of overlap is that when there are no more references to an object, it will eventually get garbage collected. And if the class implements the IDisposable interface, then Dispose() will be called on the object before it gets garbage collected.
But that won't happen immediately after you set your reference to null, for two reasons.
First, other references may exist, so it won't get garbage collected at all yet, and second, even if that was the last reference, so it is now ready to be garbage collected, nothing will happen until the garbage collector decides to delete the object.
Calling Dispose() on an object doesn't "kill" the object in any way. It is commonly used to clean up so that the object can be safely deleted afterwards, but ultimately, there is nothing magical about Dispose, it's just a class method.