Problem:

  • Product Name: VisiBroker C++
  • Product Version: All
  • Product Component: CORBA Any
  • Platform: All
The CORBA Any type provides support for dynamic typing in IDL and allows what type of data to be sent at runtime. C++ maps IDL Any type to C++ class CORBA::Any with corresponding dumb pointer Any_ptr and smart pointer Any_var.

The 2 operations on Any types are ‘<<=’ for insertion and ‘>>=’ for extraction.  Insertion of data into CORBA::Any can be categorized into primitive or complex data type.

1. Insertion of basic/primitive types will not cause memory corruption.

  // C++
  void operator<<=(CORBA::Any&, T);

It is sufficient for most basic data types T (passed by value) (ie. short, long, float).

2. Insertion of compound/complex data types.

  // C++
  void operator<<=(CORBA::Any&, const T&); // copying insertion
  void operator<<=(CORBA::Any&, T*); // consuming insertion


// IDL – Bank module
  struct Account{
    long id;
    string owner;
    long balance;
  }

How can I prevent a memory leak or corruption with CORBA::Any datatype?

Resolution:

A. Copying insertion

A copying insertion will create a ‘deep’ copy of the data and puts the copied data under the ownership of the Any.

{
  CORBA::Any theAny; // empty
  Bank::Account  accountA;
  accountA.id = (CORBA::Long)1;
  accountA.owner = CORBA::string_dup("A");
  accountA.balance = (CORBA::Long)1000;
  // ‘theAny’ makes a deep copy of ‘accountA’ and assumes its ownership
  theAny <<= accountA;
  Bank::Account_var accountB = new Bank::Account();
  accountB->id = (CORBA::Long)2;
  accountB->owner = CORBA::string_dup("B");
  accountB->balance = (CORBA::Long)1000;
  // 1. Current data referred by ‘theAny’ deleted.
  // 2. A deep copy of ‘*accountB’ created and
  // ‘theAny’ assumes its ownership.
  theAny <<= *accountB;
  CORBA::release(theAny);
}

De-allocation of original data remains the responsibility of smart pointer ‘accountB’, while the de-allocation of new copy will be with ‘theAny’.  Please use CORBA::release() to delete the CORBA object references.

B. Consuming insertion

A consuming insertion puts the original data under the ownership of the Any instead of making a copy of data like ‘copying insertion’.

{
  CORBA::Any theAny;
  Bank::Account* accountA = new Bank::Account();
  accountA->id = (CORBA::Long)1;
  accountA->owner = CORBA::string_dup("A");
  accountA->balance = (CORBA::Long)1000;
  // ‘theAny’ makes a shallow copy of the Bank::Account and assumes
  // ownership of the data
  theAny <<= accountA;
  Bank::Account_var accountB = new Bank::Account();
  accountB->id = (CORBA::Long)2;
  accountB->owner = CORBA::string_dup("B");
  accountB->balance = (CORBA::Long)1000;
  // 1. the ‘accountB’ give up the ownership by invoking _retn()
  // 2. Current data referred by ‘theAny’ deleted
  // 3. ‘theAny’ assumes the ownership of the original data.
  theAny <<= accountB._retn();
  CORBA::release(theAny);
}

However a tricky part is with a smart pointer (_var). Different from copying insertion, a smart point (_var) need to give up the ownership to the original data (by calling _retn()) before making the insertion to CORBA::Any.

*** NEVER insert a ‘_var’ directly to CORBA::Any, as it will result in both _var and CORBA::Any owning the data. Subsequently, memory corruption may occur when both try to delete the same block of memory (double deletion).