Опасности преобразования делегатов в указатели на функции - PullRequest
6 голосов
/ 11 ноября 2010

Предположим, у вас есть управляемый класс, который преобразует член-делегат в собственный указатель функции и передает его в собственный код. Предположим, что класс / делегат остается в области видимости и не изменяется в течение времени жизни нативного кода (чтобы он не был явно уничтожен GC). Какие еще проблемы нужно знать в этой ситуации? Например, может ли GC переместить делегат или фактический метод, на который ссылается делегат, и оставить свой собственный код с нарушением прав доступа?

Ответы [ 4 ]

2 голосов
/ 11 ноября 2010

Кажется, что можно закрепить место в памяти делегата / функции, но это мешает главному преимуществу .NET GC: сжатие.

После завершения очистки GC каждый объект перемещается в память, чтобы быть смежным. Это делает и доступ и распределение быстрее, чем если бы куча была фрагментирована. Если вам нужно закрепить объект на месте в куче, GC придется обойти его, и если это будет сделано несколько раз, это может привести к некоторой нетривиальной фрагментации кучи. (Кстати, об этом говорится в статье, на которую ссылается Рон Уорхолик, с помощью GCHandle. Я не уверен, что это доступно за пределами управляемого C ++.)

2 голосов
/ 11 ноября 2010

GC может перемещать делегата, но не собственный код, который переносит делегат.Таким образом, до тех пор, пока делегат не будет собран, указатель на функцию останется действительным.

Обратите внимание, что «находиться в области видимости» недостаточно для предотвращения сбора объекта.Он должен быть использован (возможно при вызове GC.KeepAlive).

2 голосов
/ 11 ноября 2010

Быстрый поиск показывает руководство Microsoft по этому вопросу. Эта статья предназначена для управляемого C ++, но руководство должно применяться для любого языка в CLR.

Идея состоит в том, что вам нужно предотвратить перемещение или удаление самого делегата, но (естественно) базовый код не может двигаться. Как только JIT компилируется в собственный код, этот код исправлен и не должен перемещаться.

2 голосов
/ 11 ноября 2010

Я не большой специалист по .Net, но, думаю, вам стоит взглянуть здесь: Маршал обратные вызовы и делегаты с использованием взаимодействия C ++ .

Обратите внимание, что это возможно, но не необходимо закрепить делегата, используя pin_ptr, чтобы предотвратить его переместить или утилизировать уборщик мусора. Защита от преждевременная сборка мусора необходимо, но закрепление обеспечивает больше защита, чем это необходимо, так как это предотвращает сбор, но также предотвращает перемещение.

...