Расширение на ответ логики.
CLR может выполнять сбор мусора только в той памяти, которая выделена и принадлежит управляемому коду. У него нет взгляда или понимания неуправляемой памяти. В случае, когда C ++ вызывает .Net DLL через COM-взаимодействие, у вас есть сочетание управляемой и неуправляемой памяти. Кроме того, у вас есть объекты C ++, которые поддерживают управляемые объекты живыми (через COM-указатели и CCW).
CLR будет правильно освобождать управляемые объекты, но только тогда, когда на них больше не будет ссылок. Когда C ++ получает доступ к управляемому объекту, он создает CCW под капотом, который поддерживается встроенным указателем COM-интерфейса C ++. До тех пор, пока счетчик ссылок на этот указатель не достигнет 0 через вызовы Release и Add, он будет поддерживать работу CCW и, следовательно, базового управляемого объекта.
Попробуйте обернуть все места в C ++, где вы получаете доступ к своему управляемому объекту с помощью CComPtr, и посмотрите, решит ли это вашу проблему.