Considerations When Using C++ Standard Library

When -cpp11 is specified on the command line, the generated code may use features of the C++ Standard Library such as std::string for character strings and std::list (or another container class) for SEQUENCE OF types. There are a few considerations to keep in mind when using this option.

ASN1C generates code that manages memory using OSCTXT and rtxMem* functions. The design of the generated code and memory management is such that the C++ constructors and destructors generally don't need to be invoked. For example, dynamic memory is allocated using rtxMemAllocType, instead of new, and initialization can be done by assigning individual fields or else using a generated asn1Init* function, so that the constructor is never invoked.

The C++ Standard Library classes are more typical C++ classes, and failing to invoke their constructor or destructor, or invoking them more than once, can lead to memory leaks or crashes. This means that when you are using the -cpp11 option, you must take care that the C++ constructors and destructors for the generated classes are invoked exactly once.

Before listing the rules to be followed, a few bits of information will be helpful:

Follow these rules to avoid problems:

A few code examples are given below.

EXAMPLE 1, Using a local variable:

   //A local variable's constructor & destructor fire automatically.  You only need to
   //make sure asn1Free* is invoked.
   //This example assume ASN1T_PDU is a PDU type (extends ASN1TPDU).
   ASN1T_PDU msgData;
   ASN1C_PDU controlPDU (encodeBuffer, msgData);

   // Populate structure of generated type
   ...

   // Encode
   ...

   // When msgData goes out of scope, its destructor will fire, which will invoke
   // asn1Free_PDU, but it won't have a context. If this were not a PDU type, 
   // the destructor would not do this and you would have to invoke asn1Free_PDU
   // yourself.
   
   // If I want memory to be freed now, I need asn1Free_PDU to be invoked with
   // a context, which I can do as follows:
   controlPDU.MemFree();

EXAMPLE 2, Assigning a dynamically allocated std::string for a choice type:

   OSCTXT* pctxt;
   ...

   //set the selector indicating which alternative is chosen
   pvalue->myChoice.t = 1;

   //allocate memory for the chosen alternative
   pvalue->myChoice.u.message = rtxMemAllocTypeZ (pctxt, std::string);

   //invoke the constructor using placement new expression
   new (pvalue->myChoice.u.message) std::string();

   //Assign the contents of the string.
   *pvalue->myChoice.u.message = "Happy Birthday!";

EXAMPLE 3, Dynamically allocating and freeing an object:

   OSCTXT* pctxt;
   ...

   //dynamically allocate and construct the object
   ASN1T_StringsInSequence* pvalue = rtxMemAllocType (pctxt, ASN1T_StringsInSequence);

   if (pvalue == NULL)
      return LOG_RTERR (pctxt, RTERR_NOMEM);

   new (pvalue) ASN1T_StringsInSequence();

   //do some work, maybe decode into pvalue
   ...

   //invoke asn1Free*, destruct, and free memory
   asn1Free_StringsInSequence (pctxt, pvalue);
   pvalue->~ASN1T_StringsInSequence();
   rtxMemFreePtr (pctxt, (void*)pvalue);