Выделение/освобождение памяти при работе с неуправляемыми C# и C++
Я работаю с некоторым неуправляемым кодом на C# и C++, и есть две вещи, которые я не понимаю, когда имею дело с памятью. Если кто-то может помочь мне понять:
Если переменная динамически выделяется под C# (с помощью new) и затем передается в неуправляемый код C++. Должна ли эта переменная память быть освобождена вручную под неуправляемым кодом C++ пользователем ?
Если переменная динамически выделяется под C++ неуправляемая (с помощью new) и затем передано в C#, можно ли с уверенностью сказать, что сборщик мусора освободит эту память ?
3 ответов:
Это действительно просто!
- зависит
- зависит
Эх, извините за это.
Это, конечно, относится только к указателям. Передача целых чисел-это прекрасно, а использование автоматического маршаллинга обычно означает, что маршаллер заботится о большинстве тонкостей (хотя все еще только в простейшем случае, так что будьте осторожны). Неуправляемый код - это неуправляемый - вы должны прекрасно понимать, как выделяется память, и как, когда и кто отвечает за очистку памяти.
- в обычных условиях C# будет отслеживать память и избавляться от нее в любое время после того, как она больше не используется на стороне C# . Он не имеет возможности отслеживать ссылки на стороне C++, поэтому одна из распространенных ошибок во взаимодействии заключается в том, что память освобождается до того, как неуправляемая сторона делает с ней (что приводит к большому веселью). Это относится только к случаям где на память ссылаются напрямую, а не при ее копировании (типичный случай -
byte[], который закреплен на время неуправляемого вызова). Не используйте автоматическую сортировку, если предполагается, что время жизни объекта/указателя, передаваемого в неуправляемый код, превышает время выполнения вызываемого метода.- в обычных условиях C# не имеет возможности отслеживать выделение памяти в коде C++, поэтому вы не можете полагаться на автоматическое управление памятью. Есть исключения (например, некоторые COM сценарии), но вам почти всегда придется управлять памятью вручную. Это обычно означает отправку указателя обратно в код C++ для выполнения освобождения, если только он не использовал какой-либо глобальный распределитель (например, CoMemoryInitialize). Помните, что в неуправляемом мире нет ни одного менеджера памяти, который вы могли бы безопасно вызвать, чтобы избавиться от памяти; у вас все равно нет необходимой информации.
Нет, так как объект выделяется в управляемой куче GC будет обрабатывать освобождение как обычно. Проблема в том, что вы должны сказать ему, чтобы он не освобождал или не изменял адрес объекта, пока он используется из неуправляемого кода, потому что GC не может знать, как долго вы собираетесь использовать объект из неуправляемого кода. Это можно сделать, закрепив объект. Смотрите ответ на Этот вопрос.
Нет, так как объект расположен на C++ неуправляемая куча GC не будет касаться его. У тебя есть чтобы освободить его самостоятельно, используйте delete.
Править: Если вам нужно выделить объект в управляемом коде и освободить его в неуправляемом коде или наоборот, полезно знать, что для этой цели существует куча ОС, которую вы можете использовать с помощью Маршала .AllocHGlobal и Маршал.FreeHGlobal вызывает из C#, там будут аналогичные вызовы в C++.
Как правило, в зависимости от того,
component/objectвыделяет память следует освободить память. Для каждогоnewadeleteтем, который сделалnew., что является идеальным. Если не следовать по таким причинам, как вы
C++программа может завершиться и не существует, когда жизненный цикл выделенной памяти подходит к концу, вашC#должен очистить и наоборот.
Comments