2013-03-12 1 views
2

Я столкнулся с кажущейся утечкой ручек, используя компонент Borland/Embarcadero TClientSocket. У меня есть приложение, которое создает несколько экземпляров TThread, каждый из которых динамически создает объект TClientSocket, подключается к его цели, отправляет несколько сообщений, а затем удаляется. Затем экземпляры TThread удаляются (используя параметр FreeOnTerminate = true). Я знаю, что это неэффективно, но оно идеально подходит для приложений приложения - максимальное количество экземпляров TThread, способных к одновременному использованию, ограничено 32. Проблема, которую я вижу, заключается в том, что существует явная проблема с утечкой окон, с которой я могу см. с помощью диспетчера задач. В попытке изолировать проблему я применил ту же проблему в одном потоковом смысле, просто динамически создавая объект TClientSocket и удаляя его снова, когда закончил с помощью одного цикла в основном потоке VCL. Это проявляет ту же самую проблему с утечкой рукоятки. Я знаю, что компонент устарел, и я знаю, что то, что я делаю, неэффективно, но я не понимаю, почему будет утечка дескриптора. Есть ли что-то, что нужно сделать с объектами TClientSocket до их удаления, чтобы удалить эту утечку дескриптора, или это ошибка в компоненте? Я использую сокет в неблокирующем режиме и назначая обработчики событий OnConnectOnDisconnect и OnSocketError.Приложение C++, вызывающее утечку Windows с использованием нескольких экземпляров TClientSocket

+0

SO_LINGER возможно? Просто гадать здесь. Я был бы удивлен, если бы это было так, как это было бы неожиданно, но стоило бы короткого, если бы вы могли получить этот гранулированный контроль над базовым сокетом. – WhozCraig

+0

@WhozCraig: 'SO_LINGER' не имеет ничего общего с ручками. Но да, возможно получить доступ к основному дескриптору 'SOCKET', используемому' TClientSocket' (через свойство 'TClientSocket.Socket.SocketHandle') и напрямую вызвать на нем функции WinSock API, такие как' setsockopt() '. –

+0

@RemyLebeu Нет ли ручки ввода-вывода за этим сокетом? I.e, если я открою 10 000 сокетов и запустил procexp, я * не * увижу пропорциональный счетчик ручек? Я только поднял его, потому что у меня была аналогичная проблема с приложением большого объема быстрого отсоединения, и это была именно проблема. после отключения, не убивая таймер задержки, ручки не были немедленно возвращены. Как я уже сказал, я полагаюсь на более узнаваемый, который похож на вас. Спасибо за информацию. – WhozCraig

ответ

1

Я использовал TClientSocket в течение многих лет, включая использование в основной теме и в рабочей нити, и я никогда не видел TClientSocket утечки любых ручек.

Однако TClientSocket делает по умолчанию в неблокирующем режиме, и в этом режиме он использует AllocateHWnd() создать скрытое окно, чтобы получить сокет события и AllocateHWnd() является не поточно-. Не видя своего фактического кода, это вероятная причина утечек, которые вы видите в коде рабочего потока. Решение этого вопроса просто не использовать TClientSocket является неблокирующим режимом при использовании в рабочем потоке. Вместо этого используйте его в режиме блокировки. В любом случае, лучше всего подходит логика на основе потоков.

Однако это не объясняет утечки, которые вы видите в коде основного потока. Я сомневаюсь, что TClientSocket на самом деле является виновником, и снова, не видя своего фактического кода, трудно сказать наверняка.

+0

Спасибо за этот ответ. Я просто взглянул на документацию Embarcadero для 'AllocateHWnd()' - на основе того, что вы говорите, что также подразумевает, что небезопасно использовать объекты «TTimer» в потоках также? – mathematician1975

+0

@ mathematician1975: yes, 'TTimer' использует' AllocateHWnd() ', поэтому' TTimer' небезопасно использовать в рабочих потоках. Но есть лучшие альтернативы для поточных таймеров, таких как 'CreateWaitableTimer()'. –

+0

Спасибо за информацию. Я думаю, что я просто переписал все, чтобы использовать блокирующий клиент. – mathematician1975