Cook Computing

 

« May 2002 »

MC++ and Covariant Return Types

Thursday 30 May

While on my covariance roll (there's more to come), its worth mentioning that although the C++ standard now supports covariant return types, Managed C++, you guessed it, does not support them when compiling managed types, i.e. classes marked with __gc.

Posted by at 07:52 AM. Permalink.

Component Pascal

Thursday 30 May

Component Pascal, described in the interesting Compiling for the .NET Common Language Runtime, does support covariant return types.

I verified this in my first (and last?) CP program:

MODULE HELLO;
IMPORT CPmain, Console;
  
TYPE 
  BaseParser = EXTENSIBLE RECORD END;
  FaultParser = EXTENSIBLE RECORD (BaseParser) END;
  
  BaseRet = EXTENSIBLE RECORD END;
  BaseRetPtr = POINTER TO BaseRet;
	
  FaultRet = RECORD (BaseRet) END;
  FaultRetPtr = POINTER TO FaultRet;
 
VAR
  bp : POINTER TO BaseParser;
  bret : BaseRetPtr;
  fp : POINTER TO FaultParser;
  fret : FaultRetPtr;

PROCEDURE (IN p : BaseParser) Foo() :  BaseRetPtr, NEW , EXTENSIBLE;
VAR tmp : BaseRetPtr;
BEGIN
  NEW(tmp);
  RETURN tmp;
END Foo;

PROCEDURE (IN p : FaultParser) Foo() :  FaultRetPtr;
VAR tmp : FaultRetPtr;
BEGIN
  NEW(tmp);
  RETURN tmp;
END Foo;
  
BEGIN
  NEW(bp);
  bret := bp.Foo();
  NEW(fp);
  fret := fp.Foo();
END HELLO.

Method Foo in FaultParser overrides Foo in the base class and returns a pointer to FaultRet instead of BaseRet. CP handles the covariant return type via a two-pronged approach. First, Foo in the derived class, although defined in the IL method signature to return a type of BaseRet, actually returns a type of FaultRet:

.method assembly final virtual instance class HELLO.BaseRet 
        Foo() cil managed
{
  // Code size       8 (0x8)
  .maxstack  8
  .locals init ([0] class HELLO.FaultRet tmp)
  IL_0000:  newobj     instance void HELLO.FaultRet::.ctor()
  IL_0005:  stloc.0
  IL_0006:  ldloc.0
  IL_0007:  ret
} // end of method FaultParser::Foo

Second, the compiler recognizes that a covariant return is required and automatically downcasts the returned BaseRet to the required FaultRet type:

IL_0015: call       instance class HELLO.BaseRet HELLO.FaultParser::Foo()
IL_001a: castclass  class HELLO.FaultRet
IL_001f: stsfld     class HELLO.FaultRet HELLO.HELLO::fret

I don't how the compiler recognizes that a method supports covariant return when referencing another CP assembly because there doesn't seem to be any metadata to indicate this (even when all the types are marked as exportable)

Posted by at 07:45 AM. Permalink.

Covariant Return Types

Thursday 30 May

Last night I was experimenting with some code to parse XML documents using XmlReader. I was representing each element type by a separate class deriving from a class called ParserBase. The base class does the basic work of moving the reader from node to node, calling the relevant virtual methods to get the derived classes to do some work. Once the element has been processed the ParserBase.Parse method returns an object containing the result of parsing the element:

class BaseParser
{
  ...
  public virtual Object Parse() { return new Object() };
}

and I would like a derived class to look like this, overriding Parse:

class FaultParser
{
  ...
  public override Fault Parse() { return new Fault() };
}

You should have guessed by now that I'm going to complain that C# doesn't support covariant return types. Code like this won't compile. Covariant in this context means that something - the return type - varies in the same direction as something else - the class type. As the class type becomes more specialized, FaultParser derives from ParserBase, the return type become more specialized, Fault derives from Object.

Covariant return types are uncontentious. Unlike other forms of covariance which I'll discuss in another post, I've not seen any argument against covariant return types. The compiler can check that their usage is statically correct and so they incur no runtime cost. Unfortunately they are not supported by the CLR.

Posted by at 07:08 AM. Permalink.

Reducing Accessibility of Virtual Methods (or Not)

Tuesday 28 May

The suggested class in the previous posting relied on the fact that in C++ you can reduce the accessibility of a virtual method in a derived class:

class Parent
{
public:
  void virtual Foo() { };
};

class Child : public Parent
{
private:
  void Foo() { };
};

However this is not possible in Managed C++ if the classes are marked with __gc (and is incidentally also not possible in C#). Another example of how languages have to be distorted in the cause of interop with other .NET languages.

Posted by at 06:46 PM. Permalink.

ATL Object Wizard Generated Classes

Tuesday 28 May

I recently noticed something about ATL COM AppWizard generated classes which puzzled me (after several years of using ATL I should have noticed it before now). The generated code looks like this:

class ATL_NO_VTABLE CTstClass : 
  public CComObjectRootEx<CComSingleThreadModel>,
  public CComCoClass<CTstClass, &CLSID_TstClass>,
  public ITstClass
{
public:
DECLARE_REGISTRY_RESOURCEID(IDR_TSTCLASS)
BEGIN_COM_MAP(CTstClass)
  COM_INTERFACE_ENTRY(ITstClass)
END_COM_MAP()
public:
  STDMETHOD(Foo)();
};

The issue that puzzled me was why do the interface method map and the interface methods have public visibility? The map macros need to be no more visible than protected for the case where map chaining from a base class is used, and I can't see why the interface methods shouldn't be defined as private because it wouldn't make sense to derive another COM class with the same CLSID as the base class. So, maybe the class should look like this:

class ATL_NO_VTABLE CTstClass : 
  public CComObjectRootEx<CComSingleThreadModel>,
  public CComCoClass<CTstClass, &CLSID_TstClass>,
  public ITstClass
{
public:
DECLARE_REGISTRY_RESOURCEID(IDR_TSTCLASS)
protected:
BEGIN_COM_MAP(CTstClass)
  COM_INTERFACE_ENTRY(ITstClass)
END_COM_MAP()
private:
  STDMETHOD(Foo)();
};

Defining the interface methods as public does allow the methods to be accessed from an instance of CTstClass but I think the default should be to prevent this and force the class to be used via the abstract interfaces. Am I missing something?

Posted by at 06:14 PM. Permalink.

Moveable Type Migration 3

Monday 27 May

I've completed the migration to Moveable Type. I've checked the pages look ok in IE6, Mozilla, and Opera (the About page required a minor tweak for it to look the same in Opera). The old Blogger archives are still available and can be accessed via existing permalinks. I've added the XML and RDF icons.

If you read this blog via Peter Drayton's rssDistiller-generated RSS file, please change your url to one of the RSS links displayed here.

The one outstanding problem is that MT strips HTML tags out of entries when generating RSS files, which means that entries which contain formatted text, for example code sample, are not very readable.

Posted by at 08:45 PM. Permalink.

Moveable Type Migration 2

Monday 27 May

Tomas Restrepo is also investigating Moveable Type. Re his point about breaking current links, I plan to retain my Blogger-generated archive files alongside the new MT generated files. This maintains the permanent links to individual items, with any new linkings to archived items pointing to the MT archives.

I managed to import my Blogger archives into MT this morning - a case of not RTFM'ing (my excuse was that I ran in a 6 mile road race yesterday and was feeling pretty tired afterwards) and the problem with Mozilla was solved by removing the document type declarations from all the templates (I'll have to look into the implications of this).

The current state of this is here - but don't link to this or the RSS channel - I'll be changing the location this evening when I finish the migration.

Posted by at 09:18 AM. Permalink.

Moveable Type Migration 1

Sunday 26 May

I've spent some time today attempting to migrate to Moveable Type. I want to generate an RSS feed and Blogger does not support this, even Blogger Pro. Also, I want some of the other features provided by Blogger Pro but I'm already paying for space on a server so it doesn't make sense to also pay for Blogger Pro.

I had no problems with installation, but Mozilla is not picking up the stylesheet for the default template I'm using and so far I've failed miserably to import archived postings from Blogger.

Posted by at 08:56 PM. Permalink.

This is a useful tip

Thursday 23 May

This is a useful tip from Sean Slavin on the dotnet list:

The IDE does have the option to link in a file. When add an existing item to your project, click the down arrow next to the open button in the dialog. Change it to 'Link'. This will not make a copy in your project directory. The linked file will also be updated whenever you change it from it's original project.

This was in response to the question "How to create a C# source lib?". The consensus of the replies seemed to be that creating an assembly is the better way of doing things but this is not entirely satisfactory in some cases:

  • You don't want to distribute extra assemblies containing library code (for whatever reason, for example to speed up downloading a smart client).
  • You only want to reuse a single class. If your assemblies are very fine grained this means that in other circumstances you will end up distributing many library assemblies whereas if they are coarsely grained you sometimes end up distributing more code than you need.

One of the problems with linking a source file into a project is version control: the source file has to be the correct version. You might not want to use the latest version that is visible in your source tree. Referencing an assembly gives you more control from this point of view

Something like the traditional object library approach would be useful and .NET almost supports this with modules. A file can be compiled to build a module which can then be used when compiling other assemblies. To build a module in C#:

csc /target:module foo.cs

This generates a file called foo.netmodule. To use this when compiling an assembly:

csc /addmodule:foo.netmodule bar.cs

This is also how you can combine code from different .NET languages into a single assembly. Unfortunately VS.NET does not support modules so you have to use a makefile or NAnt if you want to use modules. Something for the next release?

Posted by at 11:49 AM. Permalink.

WSindex contains lots of links

Wednesday 22 May

WSindex contains lots of links relating to Web Services. The Weblogs category lists all the usual suspects.

Posted by at 11:09 AM. Permalink.

C# - Const Parameters and Methods

Wednesday 22 May

Returning to the subject of the advantages MC++ has over C#, I was writing some unmanaged C++  like this yesterday:

void Foo(const string& str) 

which triggered the realisation that C# doesn't support either const parameters or const methods. Maybe this was something else that could quoted in MC++'s favour? However a test program revealed that although const parameters can be used in the methods of a managed class, methods themselves cannot be defined as const.

Classes with methods using const parameters compile as CLS-compliant, using a modifier to indicate that a parameter is const:

.method public instance void  Foo(int32 modopt([Microsoft.VisualC]Microsoft.VisualC.IsConstModifier) i) cil managed

So MC++ does have a slight edge on C# here. It would have been nice if the CLR supported the concept of const methods and parameters. Use of const may not prevent very many bugs but it may encourage a more disciplined approach to writing code.

Posted by at 09:03 AM. Permalink.

Tomas Restrepo discusses Strong Names

Sunday 19 May

Tomas Restrepo discusses Strong Names and Open Source. As I mentioned in an earlier posting here, the key file I use to build XML-RPC.NET is not included with the distribution. I suppose to be consistent with this I should make the public key available here so people could verify, if they were bothered, that an XML-RPC.NET assembly has been signed with this key. Even then there is still the problem of someone hacking into or spoofing this website, so the better solution would be to use a certificate. If I was selling .NET software then I would definitely pay the several hundred dollars a year for a certificate but until then strong naming will have to suffice.

Sam Gentile asks a question:

A good explanation. We are using strong names, signing and the GAC. I think I lost you on the part about to "identify" the originator. It was my impression that with marking the assemblies or Interops "promary", including a strong name, and fully signing it, we could gaurentee that one would know it came from our coporation. If I understand what you're saying it only ensures the signature in the assembly manifest when loaded is the same as the originator it was built with. Right?

My understanding of this is: given an assembly and the public key of a strong name, you can prove the assembly was signed with the corresponding private key. Therefore if you know for sure that the public key comes from a certain person or corporation, you know they signed the assembly. As I suggested above the problem is trusting the source of the public key. Which is where a certificate comes in. This essentially shiftts the burden of trust from the Cook Computing web site, which may completely under the control of hackers for all we know, to the Certificate Authority who issued the certificate, for example Verisign or Thawte. The code is now signed in such a way that if we have the public key of the Certificate Authority then we can determine for sure that the code was signed by Cook Computing (because Verisign or Thawte trusted Cook Computing enough to give issue me with a certificate, i.e I paid them some money, along with some sort of proof of identity). The problem of obtaining the public key or certificate of the Certificate Authority is solved by having this installed with the browser or operating system.

Going back to the original problem reported by Simon Fell, hacking the GAC can only be done if you have sufficient permissions (membership of Power Users or Administrators groups as described by Peter Drayton)). If you can do this you can also hack the certificates stored on the machine and plenty else, so the problem is really a non-problem because security would become impossible in this situation, no matter which method was used.

Posted by at 10:35 AM. Permalink.

IIS 6.0 Process Model

Thursday 16 May

I was interested by this article at O'Reilly - Previewing Windows .NET Servers, in particular the enhanced process model in IIS 6.0. I've advocated for a long time that complex server applications should be partitioned into separate processes, wherever feasible, to isolate different components of the server into their own address space. When using an unsafe language like C++ this tends to make the overall application more robust and makes it more obvious which components have faulty code. I worked on one very complex single-process application in which memory corruption bugs were still being discovered several years after the code had been written and in which inexplicable problems occurred at random intervals. With several hundred thousand lines of heavily multi-threaded code it was impossible to pinpoint the problems. Of course there is an overhead in making cross-process calls but if the server is partitioned sensibly these should not be an unacceptable overhead.

In IIS 6.0 inetinfo.exe is now a separate process with no apps running in its address space. This process controls multiple worker processes, each process running one or more apps. There is also the new concept of a "web garden" where a group of processes is configured to run an application pool. This is useful because, in addition to allowing better scalability, say a problem in a app only occurs in a rarely followed code path: in the web garden approach, if the problem occurs it will only bring down one of the processes in the web garden, leaving the other processes to continue handling the normal cases. IIS also allows processes to be recycled after handling a specififed number of requests so that the effects of leaky apps can be minimised. It also enables processes to be configured to be restarted automatically should a crash occur.

.NET App Domains are a method of partitioning .NET applications. An App Domain is the .NET equivalent of an OS process. More than one App Domain can be configured in a single OS process, with the state of each App Domain completely isolated from the other App Domains in the same process. If an unhandled exception occurs in one App Domain it only causes that App Domain to be shut down, the others being  unaffected. However this assumes that the code running in the App Domains is verifiably safe. Any unsafe code and all bets are off because there is potential for memory corruption across the App Domains. In this case the only robust approach is to isolate the unsafe code in a separate OS process.

There is still an overhead when making cross-domain calls but I don't know how this compares to the cross-process case. If it is anything like the difference between cross-process COM calls and cross-apartment calls in the same process it will be an order of magnitude or so faster. I'll have to do some research or experimentation on this.

Posted by at 08:09 AM. Permalink.

dateTime in XML-RPC

Wednesday 15 May

Some more postings on dateTime on the xml-rpc list. Although referenced by Adam Megacz' XMC spec, the XML-RPC dateTime format is not one of the formats in the W3C document on Date and Time Formats. I've not studied the ISO Standard but a posting on the xml-rpc.com from Graham Dumpleton lists says:

I have actually made one mistake here. The ISO 8601 basic format for date/time is CCYYMMDDThhmmss and is not CCYYMMDDThh:mm:ss. Ignoring the case difference, the important thing is that in the basic format you aren't supposed to use ":" to seperate the time of day components as is being done in the XML-RPC specification.

That is, the XML-RPC specification isn't using either the basic or extended formats for date/time but a conglomeration of both. A quick glance of the ISO 8601 standard isn't real clear as to whether you are allowed to do this and perhaps there basic and extended formats are just examples, the important thing simply being the seperators "-" and ":" are used when required and use of one doesn't imply that the other has to be used as long as the intent is clearly distinguishable.

One can only assume that one has not choice but to use the format CCYYMMDDThh:mm:ss. The reason is that people implementing XML-RPC clients and servers may not even realise that ISO 8601 allows other formats and only implement the example in the specification. One PHP implementation for example only implements the example in the XML-RPC specification.

It would be less confusing if any references for dateTime were dropped and the format simply stated to be YYYYMMDDTHH:mm:SS. Programming Web Services with XML-RPC also states the format is YYYYMMDDTHH:mm:SS. I suspect that there may be several implementations which assume this format and which don't support any other variant - I know of at least one ;-)

Posted by at 07:04 AM. Permalink.

Another Attempt to Extend XML-RPC

Monday 13 May

Yet another attempt to define and extend XML-RPC founders in the Dave Winer Reality Distortion Field. Adam Megacz has obviously put a lot of work into his XML Method Call Internet-Draft but like all previous attempts to address some of the shortcomings of XML-RPC I don't rate it chances of success very highly. XML-RPC is what it is, warts and all, and that is its strength I suppose. An admittedly flawed but trivial to implement protocol. Dave Winer's stonewalling of all such attempts to extend the protocol has certainly proved to be very effective.

However, I think there is a need for a better XML-RPC spec, for example to define what the dateTime value type is (see my recent posting on the XMLRPCNET list on this topic), and if such a document described common-practice workarounds to issues such as unicode strings then at least we would all be "singing from the same hymn sheet". (I always cringe when this cliche is used; I remember a situation where a CEO exhorted us to do this even though the company, and tens of millions worth of investment, had already hit the iceberg and was rapidly sinking).

Posted by at 07:25 AM. Permalink.

Lambda has a link to

Sunday 12 May

Lambda has a link to the Nice Programming Language. There is an article on Type safety in Nice which mentions covariant arrays:

In Java arrays are covariant: a String[] array can be passed to a method that expects an Object[] argument. But what happens if the method writes a Picture into the array? No error is detected at compile time. At run time, an ArrayStoreException is thrown.

This shows that arrays should not not be covariant. So why are they covariant in Java? Once again, mostly because of its limited type system. Object[] is often a poor replacement for T[] where T is a type parameter. Another reason is that covariant arrays are sometimes safe: when they are used in a read-only way.

In Nice, arrays are not covariant. Therefore run time errors like ArrayStoreException never occur. Moreover, it is still possible to use covariantly arrays while only reading from them. This require Nice's powerful type system: constrained type parameters: <java.awt.Component T> void read(T[]); can be applied to arrays whose component types are subtypes of java.awt.Component. Type checking guarantees that the array will not be written to by this method, so that there will be no run time failure.

Posted by at 08:43 PM. Permalink.

Covariant Arrays in .NET

Friday 10 May

Covariant arrays. If B is a sub-type of A, then B[] is a sub-type of A[]. I've used them in .NET without being aware of the concept. They are frowned upon in some circles because their usage cannot be made statically type-safe. Instead, a runtime type check is required when writing to the array. For example, the following sample results in an ArrayTypeMismatchException being thrown.

class A {}
class B : A {}

class _
{
  static void Main()
  {
    B[] bArray = new B[] { new B(), new B() };
    A[] aArray = bArray;
    aArray[0] = new A();      // runtime error
  }
}
Posted by at 07:59 AM. Permalink.

Bertrand Meyer is also a

Thursday 9 May

Bertrand Meyer is also a bit confused about what Managed C++ is (see earlier postings here). In his article Polyglot Programming he writes:

C++ typifies the Procrustean solution: Make the language fit the model. To be more precise, on .NET, the name "C++" denotes not one language, but two: Unmanaged and Managed C++. Classes from both languages can coexist in an application: Any class marked __gc is managed; any other is unmanaged. The unmanaged language is traditional C++, far from the object model of .NET; unmanaged classes will compile into ordinary target code (such as Intel machine code), but not to the object model. As a result, they don't benefit from the Common Language Runtime and lack the seamless interoperability with other languages. Only managed classes are full .NET players.

Unmanaged classes do not compile into machine code when compiling an application with the /clr switch. They are not managed on the .NET garbage-collected heap but they certainly compile to IL. Again the difference between managed code and managed types. Write a simple program and run ILDASM on it to see what I mean.

Posted by at 06:56 AM. Permalink.

I've received a couple of

Wednesday 8 May

I've received a couple of emails about a missing key file if you try to build XML-RPC.NET from the distribution. The problem is that I've generated my own key file using sn.exe (Strong Name Utility) and I want to reserve this for use only with assemblies I distribute. Therefore CookComputing.key is not included in the distribution. The workaround is to either generate your own key file using sn.exe or comment out the following line in AssemblyInfo.cs:

[assembly: AssemblyKeyFile("..\\..\\..\\CookComputing.key")]

(Tony - hope you read this here - replies to your email bounced.)

Posted by at 07:48 AM. Permalink.

Mozilla - Web Browser of Choice

Wednesday 8 May

Like mpt I am now using Mozilla as my web browser of choice. I'd rather not use client software which is integrated with the operating system (whatever that means) and IE continually crashes on my system since I installed some amazingly bad VPN client software from a company whose research labs used to be held with the highest regard (is it a useful rule of thumb that the more impressive the research labs the worse the actual software products a company sells?). I've had some problems with Mozilla on a couple of sites but on the whole it seems faster and doesn't crash when the VPN client software is running. From an ideological point of view there is also the feelgood factor of doing something (however pathetically small) to support the Internet as a non-proprietary environment.

Posted by at 07:15 AM. Permalink.

A while ago I posted

Monday 6 May

A while ago I posted some proof of concept code on the XMLRPCNET list for using the .NET RealProxy class to generate automatically XML-RPC proxies. This would save some work in implementing an XML-RPC proxy - it would only be necessary to define an interface and not implement a call to Invoke for each method.

However I came across this posting on the .NET list which describes how Remoting does not work in a partially trusted scenario. This suggested that there might be similar problems with using RealProxy. So I placed the sample code in a WinForms application and tested running it from an Internet site with various code access security permissions. Through trial and error I discovered that the following permissions are the minumum permission set for running the RealProxy sample code:

  • Security - Enable assembly execution
  • Security - Allow calls to unmanaged assemblies
  • Security - Extend infrastructure

The first of these is obviously required for any code but the other two are a bit more obscure. Anyway, this means that the RealProxy approach is not worth pursuing, and I suspect any other custom approach which involves code generating proxy code at runtime is going to run into similar problems.

Posted by at 04:37 PM. Permalink.

If you ever find that

Sunday 5 May

If you ever find that the Properties window in Visual Studio .NET won't appear when you click on its tab, press Shift when clicking on the tab and the window reappears (in pinned mode instead of slide-out mode).

Posted by at 02:27 PM. Permalink.

Thanks to Peter Drayton for

Sunday 5 May

Thanks to Peter Drayton for describing some features of MC++ which are not supported in C#, and some sample code:

I don't think these are quite compelling enough to persuade me to prefer MC++ over C# for managed work.

Interesting to note that even MC++ doesn't expose all of the CLR's exception handling capabilities. This discussion has been useful in making me realise I need to know more about the relationship between IL+CLR and the languages that sit on top of them. A quick search on Amazon brings up the following book as maybe worth looking at: Compiling for the .NET Common Language Runtime by John Gough.

Posted by at 12:28 PM. Permalink.

An interesting point - following

Friday 3 May

An interesting point - following on from the Managed C++ discussion - is whether a Managed C++ program using unmanaged features such as MI and templates would run on a different machine architecture. Is the generated IL + Metadata completely x86 independent? If so, this would be a reason for compiling a conventional C++ program as managed (assuming all the relevant .NET pieces were ever ported to a different architecture).

Posted by at 07:02 PM. Permalink.

Far from correcting any assertions

Friday 3 May

Far from correcting any assertions I've made here about Managed C++, I'd like to restate two points.

  1. The sample program listed in an earlier posting , when compiled with the /clr option, is a managed program. The result of the compilation is an assembly containing metadata and IL. This is managed code (Challa and Laksberg discuss this in Chapter 2 of Essential Guide to Managed Extensions for C++). Note that I am not saying that the program uses managed types. The program illustrates my point that Managed C++ - when using unmanaged types - can lead to code which contains the bugs that are found in tradititional C and C++ programs, even when writing completely new managed code. When defining a type, the default behaviour is that the type is unmanaged which makes errors even more likely.
  2. My other point was that I fail to see what advantages Managed C++ brings you over C# if you are not doing any interop with legacy code and intend to use only managed types. I can only see disadvantages. Various people have commented on the power of Managed C++ but I have yet to see anyone list the reasons why it is more powerful than C# in a purely managed context. I may be wrong, but if so it is because I am overlooking one or more features of Managed C++, not because the facts I have presented so far are incorrect.

In writing about this my main concern has been to find out why Managed C++ is thought to be more powerful than C# in a purely managed application. If anyone can point out which compelling features of Managed C++ I'm overlooking, please let me know. I'm open to persuasion but until then I'm definitely in the C# camp.

Posted by at 06:41 PM. Permalink.

Sam Gentile replies to my

Wednesday 1 May

Sam Gentile replies to my previous posting:

Umm, there is nothing managed about this "Managed C++" program and thus you will not get any of the CLR benefits. I think you may be confused about Managed C++ and this is common. As I say in my book, in Chapter 7, compiling with /clr will not make *any* of your data managed. It just changes compilation to emit IL in an assembly. All of the data is *still unmanaged* and coming from the unmanaged heap. That's why you have the problems above. Only the types you specifically mark with __gc or __value will become managed and the problems will go away.

My understanding is that managed code and managed types are orthogonal to each other. Managed code (produced when using the /clr option) consists of IL and metadata - which is what I see when I compile this sample program and look at its assembly using ILDASM, I don't see any native x86 unmanaged code. Managed types are allocated in a garbage collected heap and their deallocation is under the control of the garbage collector. Managed code can use unmanaged types. Hence the gist of my posting that using Managed C++ is likely to result in code which suffers from all the problems of C and C++.

A corollary to this: if you code using Managed C++ with only Managed types, and so produce safer code (but lose much of the power of C++), what advantage does Managed C++ bring you over C#? I can see disadvantages - such as the need for header files in programs with more than one source file and having to use __gc (and being careful never to omit it) - but I can't see any advantages. This is not argument for the sake of argument, I see comments such as this (Stan Lippman on an application strategy for Managed C++ in the foreword to Essential Guide to Managed Extensions for C++):

Writing directly in the .NET environment the same as you do in C# or Visual Basic, but with more access to the underlying .NET architecture

and wonder what it is I'm missing.

Posted by at 07:56 AM. Permalink.