Search code examples
c++dynamicdelete-operator

Who is responsible for delete?


I was analyzing a code and I am confused on a particular code. I have posted the code/pseudo-code which will convey the same meaning.

Class 1

Class1::Func1()
{
    Collection* cltn;   
    try
    {
        cltn = Class2::get_records_from_db();
    }
    catch(Informix error)
    {}
    catch(DB Error)
    {}
    catch(...)
    { Unknown exception }          //I get this error always once the process processes lot of records   
}

Class 2

Collection* Class2::get_records_from_db()
{
    Collection *clt = new Collection();
    try
    {

        //Query database
        For each row in query result
        Row *row = new row();
        populate(row)
        clt->add(*row)

         ...
        if( Informix error)
        {
            throw Informix error;
        }  
     }

     catch(...)
     {
          delete clt;  //Who will delete row?
          clt = 0;
          throw Db error 
     }

    return clt;  //Who will delete clt?
}

Problem - PART 2

Thanks for the insights on the first problem. Now here is the real problem which is happening.

Class 1 is a C++ process and Class 2 is a library which talks to Informix database. Class2::get_records_from_db() is a function which queries an Informix DB and returns the result-set. I have enhanced the above code which is more similar to the real code.

Collection objects deals with 200k of row objects, which as most of you said is not released properly.
The caller is seeing "Unknown exception" in the general catch block. Can that be because of the huge memory leaks created in Class 2?

I also see some Informix errors 406 (Out of memory error) in the logs. The process core-dumps after spitting out a series of Unknown Exception & SQLERR406

I want to know whether the core dump is a byproduct of the memory leaks.


Solution

  • What is the problem with the code you presented?

    The code example you present is a very bad and wrong code.

    No one deletes either of (row and clt) them. This leads to a memory leak or a Undefined Behavior depending on whether their destructors have trivial or nontrivial implementation.Either way it means very bad things can happen.

    If you allocate an object using new you need to explicitly deallocate it by calling delete on the pointer returned by new. Since you do not call delete on either of the pointers, they both are never deallocated at all.

    Who should be responsible for delete?

    The objects themselves!
    The objects should have an inbuilt functionality to de-allocate themselves as soon as their scope({,}) ends. This way no one needs to explicitly deallocate any of the objects, but they get implicitly deleted once they are not needed anymore. This technique is popularly known as Resource Allocation is Initialization(RAII) or Scope Bound Resource Management(SBRM) in C++.

    Each of your objects(row and clt) should be using a RAII by writing wrappers over these raw pointers or even better simply by using readily available Smart pointers.