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. Follow these rules to avoid problems:
When you dynamically allocate an object, use rtxMemAlloc*
to allocate the memory, then use a placement new expression to invoke the constructor.
C++ destructors don't have access to an OSCTXT
for use in freeing memory. Therefore, before an object is destructed, invoke the generated asn1Free*
function for that type to free any dynamically allocated memory that is directly or indirectly owned by the object. If no asn1Free*
function was generated for the type in question, there is no such memory that needs to be freed and this rule does not apply.
If you dynamically allocate an object that is not owned by some other object, make sure when you are finished with the object that you do the following three things, in order:
invoke the generated asn1Free*
function, if there is one. This will recursively destruct and free memory for objects directly or indirectly owned by the object.
explicitly invoke the destructor for the object. This will recursively destruct objects contained by the object.
use rtxMemFreePtr
to release the memory
If you repeatedly use the same object to encode records, use the asn1Init* method with free=TRUE to free previously allocated data before repopulating the object. If you repeatedly decode into the same object, invoke the Decode method with free=TRUE.
Do not use ASN1CType.memReset(). You must use the asn1Free* methods or else memory allocated by the C++ standard library will not be freed. Also, invoking an asn1Free* method after ASN1CType.memReset() is likely to cause a segmentation fault as dangling pointers are followed.
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. Using a control class, as show here, does that for you. ASN1T_PDU msgData; ASN1C_PDU controlPDU (encodeBuffer, msgData); // Populate structure of generated type ... // Encode ... // When controlPDU goes out of scope, asn1Free_PDU will be invoked on msgData // When msgDta goes out of scope, its destructor will fire
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);