Recent Changes - Search:

Mcp

edit SideBar

MCP - Managed C++ for GCC

This project aims to provide Managed C++ for GCC via its plugin facilities.

Getting Started

Synopsis

MCP aims to provide not just a garbage collected C++ but one that is very similar to Microsoft's C++/CLI. It uses Boehm GC as its garbage collector. While BoehmGC can be easily employed in any C++ projects to enable automatic garbage collection, it can only run in conservative mode. Furthermore, its built-in C++ support mode (via gc_cpp.h) causes the new operator to get replaced globally, making all allocated objects / memory to be conservatively tracked (further reading on conservative GC). This method is both slow (because the entire heap would have to be checked) and causes a lot of false retentions. There are ways to get around this by selectively creating heap memory that is not traced (GC_MALLOC_ATOMIC) but the GC passes this responsibility back to the programmer. This needs to be avoided -- let's face it, no one wants the burden of deleting objects to be replaced by one that requires you to use different mallocs at different times. Furthermore, gc_cpp.h also does not provide C++ programmers with an interface for such functionalities.

While it is true that both GCJ (GNU Compiler for Java) and Mono (the cross-platform open-source .NET development framework) also use Boehm GC as their default garbage collector, they are not, however, using it in fully conservative mode. While stack scanning remains conservative (this is usually not a problem in a mainly managed app -- see Usage Recommendations section), all heap objects use Boehm GC in precise mode.

This project therefore aims to provide the same GC tracing precision in C++, as well as providing as much language similarities to Microsoft's C++/CLI as possible within the confines of C++11.

For example,

In C++/CLI,

ref class Foo
{
    // ...
};

Foo^ foo = gcnew Foo();
// Array of Foo's
array<Foo>^ foos1 = gcnew array<Foo>(100);
// Array of Foo pointers
array<Foo^>^ foos2 = gcnew array<Foo^>(100);
// Jagged array (array of arrays):
array<array<Foo^>^>^ foos2 = gcnew array<array<Foo^>^>(100);
// Multi-dimensional array:
array<Foo^, 2>^ foos3 = gcnew array<Foo^, 2>(100, 2);

MCP equivalence,

__ref_class Foo
{
    // ...
};
typedef gc_ptr<Foo> Foo_P;

Foo_P foo = gcnew (Foo)();
// Array of Foo's
array_P<Foo> foos1 = gcnew (array<Foo>)(100);
// Array of Foo pointers
array_P<Foo_P> foos2 = gcnew (array<Foo_P>)(100);
// Jagged array (array of arrays):
array_P<array_P<Foo_P>> foos2 = gcnew (array<array_P<Foo_P>>)(100);
// Multi-dimensional array:
array_P<Foo_P, 2> foos3 = gcnew (array<Foo_P, 2>)(100, 2);

Usage Recommendations

In a mainly managed application, the stack is usually very shallow as most objects / arrays should be created using gcnew. These objects reside in the heap memory and are precisely traced to guarantee no false retentions. As written in Boehm GC's white paper, compressed data and bitmaps are the only types of data that would cause a high amount of false retentions. Since these objects do not reside on the stack, false retentions would be minimal for MCP. It would be about the same as GCJ and Mono as long as you keep to this coding recommendation -- keep the stack shallow by creating arrays / objects on the heap memory via gcnew.

Worst case scenario -- e.g. call out to a legacy library that creates objects on the stack that causes a lot of false retentions, you get as much false retentions as you would a conservative mode GC. Do keep in mind though that GCJ / Mono would have the same false retentions too if they were to call out to the same library.

Edit - History - Print - Recent Changes - Search
Page last modified on February 20, 2013, at 11:36 PM