2005/5/10

     
 

Dangerous constructs

artefaktur

| References | Casting | Arrays | Import | instanceof | Package | Synchronization | Throwable | finally | Dangerous | Stack | String |

In ACDK, there are some constructs that should be avoided.

Content of this chapter:

         Dangling Pointer on using this in constructors
         Dangling Pointer with RString::c_str()
         Free this if using raw Object pointer

 Dangling Pointer on using this in constructors

class AClass
: public Object
{
public:
  int _ival;
  AClass()
  : Object()
  {
    foo(this);//oops, this will delete this!!!
    _ival = 0; // segmentation fault
  }
  void foo(RObject o)
  /* what happend here is:
     o.impl->refCount is 0.
     Constructor of RObject increment it to 1.
  */
  {
  } /* here the destructor of RObject will be called.
      The Destruktor decrement o.impl->refCount,
      o.impl->refCount is 0 -> delete o.impl.
    */
The usage of this in the constructor should be avoided. Instead, you can use the following construct:

  //....
  AClass()
  : Object()
  {
    ACDK_SAFE_CONSTRUCTOR(); // to prevent delete this
    foo(this);
    _ival = 0;
  }
  //....
 Dangling Pointer with RString::c_str()

RString
getAString()
{
  RString str2 = new String("Hallo");
  return str2;
}

void
foo()
{
  RString tstr = getAString();
  // we know tstr contains a ascii string, otherwise the string has to be converted
  const char* ptr = tstr->c_str(); // This is OK, because tstr holds reference
  doIt(getAString()->c_str()); // This is also OK
  /*
   The following is NOT OK, because the returned RString (and containing buffer)
   will be destroyed immediately after returning it.
  */
    const char* aptr = getAString()->c_str();
    doIt(aptr);// !!!! aptr is dangling pointer !!!!
}
 Free this if using raw Object pointer
Because ACDK objects are C++ objects you can use it following way:

// should not use this, really
StringBuffer* sb = new StringBuffer("Hello ");
delete sb;
but in the case you call, which converts the this pointer of this objects to a RefHolder (here RStringBufer), the sb object will deletet by this RefHolder.

StringBuffer* sb = new StringBuffer("Hello ");
sb->append(" World"); 
// append returns this as RStringBuffer 
// sb will be freed by the temporary returned RStringBuffer!
delete sb; // crash!
To avoid this you can use following constructs:

StringBuffer* sb = new StringBuffer("Hello ");
sb->addRef(); // prevents for freeing
sb->append(" World"); 
sb->releaseRef(); // will free the underlying object.
// sb no longer valid
<source>

or alternativally:
<source>
StringBuffer* sb = new StringBuffer("Hello ");
sb->lockMem(true); // locks memory, doen't free by GC
sb->append(" World"); 
delete sb; //ok
// sb no longer valid

 < prevConstructs(10 / 12) next >