Это может быть непрактично в вашем случае, но то, что я делал однажды, когда у меня была похожая проблема с открытыми соединениями с базой данных, было переопределением функции "open" моей собственной. (Удобно, что у меня уже была эта функция, потому что мы написали свой собственный пул соединений.) Затем в свою функцию я добавил запись в таблицу, записывающую открытие. Я сделал вызов трассировки стека и сохранил идентификатор вызывающего абонента вместе с временем вызова, и я забыл, что еще. Когда соединение было освобождено, я удалил запись в таблице. Затем у меня был экран, на котором мы могли вывести список открытых записей. Затем вы можете посмотреть на отметку времени и легко увидеть, какие соединения были открыты в течение невероятного количества времени и какие функции выполняли эти открытия.
Из этого мы смогли быстро отследить пару функций, которые открывали соединения и не могли их закрыть.
Если у вас много открытых дескрипторов файлов, есть вероятность, что вы не сможете закрыть их, когда закончите где-нибудь. Вы говорите, что проверили правильные блоки try / finally, но я подозреваю, что где-то в коде вы либо пропустили плохой, либо у вас есть функция, которая передает и никогда не добирается до конца. Я полагаю, также возможно, что вы действительно делаете правильные закрытия каждый раз, когда открываете файл, но вы открываете сотни файлов одновременно. Если это так, я не уверен, что вы можете сделать, кроме серьезного редизайна программы, чтобы манипулировать меньшим количеством файлов, или серьезного редизайна программы, чтобы поставить в очередь доступ к вашим файлам. (На этом этапе я добавляю обычное: «Не зная деталей вашего приложения и т. Д.»)