in

MSMVPS.COM

The Ultimate Destination for Blogs by Current and Former Microsoft Most Valuable Professionals.

Cluebat-man to the rescue

A weblog dedicated to Visual C++, interoperability and other stuff.

Differences between C++ and C#, part 3

One of the things that C# (and VB.NET) programmers have to live with is non-deterministic destruction of their objects.

The garbage collector was introduced in .NET to take care of memory leaks and remove the need for manual memory management. It does this by keeping track of references, and as soon as an object is no longer referenced, it ‘can’ be collected by the garbage collector.

The ‘can’ is important here, because cleanup happens only when the GC thinks is should happen. On systems with lots of memory, and few memory allocations and releases, it is possible that this takes minutes or hours, or even doesn’t happen at all.

This can be a real problem, because now you don’t have memory leaks anymore, but resource leaks.

Suppose your app opens a file for writing, and does not explicitly dispose of the stream reference.

FileStream stream =
  new FileStream(Path.GetTempFileName(), FileMode.Open);
StreamWriter writer = new StreamWriter(stream);writer.WriteLine("Hello, world.");

writer.Close();

The file is written and flushed to disk, but as long as the garbage collector does not collect the ‘stream’ object, it will hold an open file handle that will prevent you or anyone else from accessing that file. To overcome this you have to make sure that the file is released. On way of doing that would be like this:

FileStream stream = new FileStream(Path.GetTempFileName(), FileMode.Open);
try
{
  StreamWriter writer = new StreamWriter(stream);
  writer.WriteLine("Hello, world.");
  writer.Close();
}
finally
{
  stream.Dispose();

}

You could also use the ‘using’ keyword, but the same holds true. It is easy to make mistakes, and if you have several of such objects in the same scope, then your code will become a convoluted mess of nested try/finally or using constructs.

In C++/CLI, this problem can be solved differently.

In native C++, they way you create an object determines whether it will live on the stack or in the heap. The location implies the way the object will be cleaned up. If it is on the stack, it will be released automatically when it goes out of scope.

C++/CLI does not have the ability to create managed objects on the stack, but it supports stack like semantics. I.e. even if you use the declaration that would put the object in the stack, it is still created in the managed heap. But the syntax and the semantics are stack based.

This means that in the following example, the stream object will automatically be released when it goes out of scope.

FileStream stream(Path::GetTempFileName(), FileMode::Open);
StreamWriter writer(%stream);
writer.WriteLine("Hello, world.");

writer.Close();

And regardless of how many such objects we need to create or use locally, they will all be cleaned up automatically without needing ugly nested structures, and without needing extra lines of code.

Of course, you still have to determine if this is something you want, because sometimes you need objects to live beyond the scope in which they were created. In that case you can use the gcnew operator to use heap semantics.

FileStream^ stream = gcnew FileStream(Path::GetTempFileName(), FileMode::Open);

C++ gives you the ability to choose the best approach, which is nice if you want to write correct code without wanting to increase the number of lines of code, and structural complexity.

Only published comments... Feb 27 2008, 05:52 AM by vanDooren
Filed under: ,

Leave a Comment

(required)  
(optional)
(required)  
Add


Copyright © is the original authors. Blog site is an independent site not sponsored by Microsoft. The Yoda blog server and the Brianna SQL server would like to thank www.ownwebnow.com and www.exchangedefender.com. They wouldn't be here and broadcasting without the generosity of Vlad Mazek and his companies.

Powered by Community Server (Commercial Edition), by Telligent Systems