0

To send data to multiple clients I create a TIdThreadSafeStringList in OnConnect and assign it to AContext->Data like so

AContext->Data = new TIdThreadSafeStringList

When the client disconnects, its stringlist is deleted in OnDisconnect like so

delete AContext->Data

However this results in an AV. If I zero the parameter, like so

delete AContext->Data
AContext->Data = NULL

the AV goes away. Is there some auto cleanup I'm not aware of?

Using C++ Builder 10.2.3.

Mike Versteeg
  • 1,615
  • 14
  • 28

1 Answers1

1

Is there some auto cleanup I'm not aware of?

Yes. TIdContext derives from TIdTask, which owns the Data property. The TIdTask destructor is called after the OnDisconnect event and will free the Data object if it is not NULL.

Another (preferred) way to handle this situation is to instead derive a new class from TIdServerContext and add your TIdThreadSafeStringList to that class (and any other per-client custom functionality you want), eg:

class TMyContext : public TIdServerContext
{
public:
    TIdThreadSafeStringList *MyList;

    __fastcall TMyContext(TIdTCPConnection *AConnection, TIdYarn *AYarn, TIdContextThreadList *AList = NULL)
        : TIdServerContext(AConnection, AYarn, AList)
    {
        MyList = new TIdThreadSafeStringList;
    }

    __fastcall ~TMyContext()
    {
        delete MyList;
    }

    //...
};

Then assign your class type to the server's ContextClass property at runtime before activating the server, eg:

__fastcall TMyForm::TMyForm(TComponent *Owner)
    : TForm(Owner)
{
    IdTCPServer1->ContextClass = __classid(TMyContext);
    //...
}

Then, you can simply type-cast any TIdContext* pointer belonging to the server to your class type in order to access the TIdThreadSafeStringList (or other functionality):

static_cast<TMyContext*>(SomeIdContext)->MyList->...

This way, you can ignore the TIdContext::Data property altogether, or use it for other purposes, if desired.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • "The TIdTask destructor is called after the OnDisconnect event and will free the Data object if it is not NULL." - I read that (except the last part about it not being NULL) but didn't understand. How can it free the object if it can't know what it is? – Mike Versteeg Apr 12 '19 at 05:29
  • 1
    @MikeVersteeg it doesn't need to know the object's type. All objects derive from `TObject`, and `TObject` has a virtual destructor. `Data` is a `TObject` pointer, and freeing an object via a base `TObject` pointer is a safe operation, the object will be destroyed properly regardless of its actual type. This is one of the key features of polymorphism. – Remy Lebeau Apr 12 '19 at 08:28