[omniORB] Help with allocating and deallocating - Try again

Duncan Grisby dgrisby@uk.research.att.com
Tue, 12 Oct 1999 10:43:03 +0100


On Monday 11 October, David Hyde wrote:

> // The Session object.  This is declared globally in the cpp file
> CBSession_ptr g_pSession;
> 
> 
> // Later on we see if we have a connection to g_pSession
> if (CORBA::is_nil(g_pSession))
> {

This is the first (minor) error, although it has nothing to do with
your problem. The CBSession_ptr is initialised to zero, but the CORBA
C++ mapping does not require that nil object references are mapped to
zero pointers. Indeed omniORB maps nil to a pointer to a singleton nil
object. So, calling is_nil() on a zero pointer is strictly-speaking
incorrect. However, omniORB is generous and lets you get away with
it. If you run with an ORB trace level greater than 10, you'll get a
warning.

> 			g_pSession =
> CBSession::_duplicate(pSessFactory->create());

The duplicate() here is wrong. The ownership rules for object
references says than ownership of a returned object reference is
passed to the caller. You should just say

  g_pSession = pSessFactory->create();

On the server side, your factory should make sure it returns a
correctly reference counted object reference with a call to _this(),
like:

  CBSession_i* si = new CBSession_i(...); // Create servant
  return si->_this();                     // Return object reference


> // Later still we've finished with g_pSession, so I get rid of it.
> // I don't use delete and I don't set it to to NULL because the
> documentation says not to do
> // this with CORBA pointers		
> CORBA::release(g_pSession);
>
> // Now we want to use g_pSession again, but we have to have a new one made
> for us because we've got rid of the
> // old one.  We do this again.
> if (CORBA::is_nil(g_pSession))
> {
> 	...
> 
> 
> I would have thought that is_nil should return TRUE, but it returns FALSE.

This is because you haven't set the pointer to nil!  The code you've
written is basically equivalent to the simple C++:

  int* p = 0;
  p = new int;
  delete p;
  if (p==0) {
    ...

The call to CORBA::release() just indicates that you are no longer
using the object reference. It does nothing to the pointer. You should
say:

  CORBA::release(g_pSession);
  g_pSession = CBSession::_nil();
  if (CORBA::is_nil(g_pSession) {
    ....

and you'll find that is_nil() returns true.


> When I try to use the g_pSession object that I now think is valid the
> program crashes.  I've wondered if I am doing something to screw up the
> reference counting, so I tried CORBA::release on g_pSession twice in the
> above code.  Stepping into the OmniOrb code, during the first release(), I
> see that g_pSession's reference count is two.  If I do the double release,
> though, the CORBA::is_nil call throws an exception. What I can say is that
> the first call to release is definitely causing the Session object's
> destructor to be called.

I'm not quite sure what is going on here. Given your earlier
superfluous duplicate(), I would expect the object reference to remain
valid after the first release(), and to be deleted after the second.

Cheers,

Duncan.

-- 
 -- Duncan Grisby  \  Research Engineer  --
  -- AT&T Laboratories Cambridge          --
   -- http://www.uk.research.att.com/~dpg1 --