Bug? Borland C++ with SmallObj and Singleton

2002-09-12
2013-04-08
  • My acquaintance is using Borland C++, and he has encountered
    a dangling-pointer problem when he executed the code below.

    I think that when WinMain() exits, OnDestroy of the Form is called
    after the Singleton object is destructed,
    So, if we make a SmallObj in a contructor of a Form and
    delete it in OnDestroy, disaster happens.

    Does anyone know work around about this?

    ---- WinMain() ------

    WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
    {
        try
        {
             Application->Initialize();
             Application->CreateForm(__classid(TForm1), &Form1);
             Application->Run();
        }
        catch (Exception &exception)
        {
             Application->ShowException(&exception);
        }
        catch (...)
        {
             try
             {
                 throw Exception("");
             }
             catch (Exception &exception)
             {
                 Application->ShowException(&exception);
             }
        }
        return 0;
    }

    ---- MySmallObj ------

    class MySmallObj
        : public Loki::SmallObject<Loki::ClassLevelLockable>
    {
    public:
        __fastcall MySmallObj() : a(3) {};
        ~MySmallObj() {};
        int a;
    };

    ---- Form1(MainForm) ------

    TForm1 *Form1;
    MySmallObj *SmallObj;
    //--------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
    {
        SmallObj = new MySmallObj;
    }
    //--------------------------------------------------------------
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
        Label1->Caption = SmallObj->a;    //BottonClick&#12391;&#20516;&#12434;&#34920;&#31034;
    }
    //--------------------------------------------------------------
    void __fastcall TForm1::FormDestroy(TObject *Sender)
    {
        delete SmallObj;   
    }
    //--------------------------------------------------------------

     
    • Try changing the lifetime policy of the SingletonHolder (in SmallObj.h) from PhoenixSingleton to DefaultLifetime.

      It should throw a std::logic_error if it's a dead reference problem.

       
    • > Try changing the lifetime policy of the SingletonHolder
      > (in SmallObj.h) from PhoenixSingleton to DefaultLifetime.
      >
      > It should throw a std::logic_error if it's a dead reference problem.

      Still got a same error which is raised from an assert statement in
      the destructor of FixedAllocator.

        SmallObj.cpp : FixedAllocator::~FixedAllocator()
          ...
          "assert(i->blocksAvailable_ == numBlocks_);" << Here
          ...

      A Singleton object which was made by SmallObject, is destroyed
      after the exit of WinMain().
      In Borland C++, it seems that OnDestroy of the Form is called
      after the destruction of the Singleton object.
      So, if we create a SmallObj in a constructor of some Forms,
      and delete it in OnDestroy, Singleton for SmallObj vanishes,
      and assertion failed.

       

    • Anonymous
      2003-01-31

      I get this exact same assertion if I include a SmartPtr in a form. It doens't matter if I do anything with it. If I simply include a type of Loki::SmartPtr<int> in the private section of a form declaration, i get this assertion when the applicatinon exits.

       

    • Anonymous
      2003-01-31

      The solution seems to be not to have any forms auto created, but simply create forms dynamically.

      So if you change the WinMain function in the following way:

      WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
      {
      try
      {
      auto_ptr<TMainForm> mainForm (new TManiForm(0));
      Application->Initialize();
      mainForm->ShowModal();
      Application->Run();
      }
      catch (Exception &exception)
      {
      Application->ShowException(&exception);
      }
      catch (...)
      {
      try
      {
      throw Exception("");
      }
      catch (Exception &exception)
      {
      Application->ShowException(&exception);
      }
      }
      return 0;
      }

      This seems to work for me anyway.

       
      • I would be uncomfortable with this solution.
        Borland uses the first auto-created form as the 'main form' of the application, so sets up certain flags and states associated with it.  By removing ALL auto-creation you have an application without a main form.  I'm not sure what consequences will follow, but expect to find some.

        Note: You could also remove Application->Run from this code, as the ShowModal() call serves the same purpose for you now.

        Anything further (on this solution) probably belongs in a borland forum rather than Loki though <g>

         
    • Fraser
      Fraser
      2009-08-03

      OnCreate and OnDestroy are generally not used.  The forms constructor and destructor are more suitable.

      Many parts of Loki won't compile with C++ Builder.