Memory leak in version 9 TIdTCPServer. Help!

Giganews Newsgroups
Subject: Memory leak in version 9 TIdTCPServer. Help!
Posted by:  Clayton Arends (nospam_claytonarends@hotmail.com)
Date: Mon, 4 Apr 2005

Greetings,

I have been using INDY for quite some time for all of my socket tasks.  My
latest client/server project has been plagueing me with an occassional "out
of memory" or "not enough storage" or "socket errors" on the server after a
long period of time.  After many tests I discovered a slight memory leak
after every iteration of a connection to my server.  Obviously I doubted my
own code so I decided to make a simple test application.

The test application has a single TIdTCPServer on a form.  I created a
thread that creates a TIdTCPClient and simply connected and disconnected
followed by a milisecond sleep.  Very quickly I saw the memory consumption
sky-rocket in the task manager.  After a very short period of time I
received an EThread exception "Thread creation error: Not enough storage is
available to process this command".

The guts of the application are simple.  The server has an OnExecute handler
that simply sleeps for a milisecond and returns.  The client thread simply
connects then disconnects.

I am using BCB6 on XP Pro SP2 and INDY 9.0.18.  Though I've tried every
version between 9.0.11 and 9.0.18 with the same memory leak results.  Here
is the source:

  #include <vcl.h>
  #pragma hdrstop

  #include "Unit1.h"
  #pragma package(smart_init)
  #pragma resource "*.dfm"
  #include <memory>

  TForm1 *Form1;

  class TTestThread : public TThread
  {
    public:
      TTestThread() : TThread(false) {}

      void __fastcall Execute()
      {
        while (!Terminated)
        {
          TIdTCPClient* client = new TIdTCPClient(NULL);
          std::auto_ptr<TIdTCPClient> auto_client(client);
          client->Host = "localhost";
          client->Port = 777;
          client->Connect();
          client->Disconnect();
          Sleep(1);
        }
      }
  };

  TTestThread*  thread;

  __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
  {
  }

  __fastcall TForm1::~TForm1()
  {
    thread->Terminate();
    thread->WaitFor();
    delete thread;
  }

  void __fastcall TForm1::Button1Click(TObject *Sender)
  {
    thread = new TTestThread;
  }

  void __fastcall TForm1::IdTCPServer1Execute(TIdPeerThread *AThread)
  {
    Sleep(1);
  }

Note, if I remove the server from the form and allow it to be created and
destroyed in the thread then there is no memory leak.  Can someone else
please verify that this happens in their BCB or Delphi environment?  I can't
believe that a memory leak this severe can have gone unchecked for so long
and am hoping that there is something I can do to fix.

TIA,
- Clayton

Replies