Если вы получили это предупреждение MDA, то вы точно повторили проблему.Да, это будет тяжелый сбой без отладчика, нативный код будет бомбить при обратном вызове.Заглушки, которая выполняет маршал вызова от нативного к управляемому коду, больше нет.Вероятность для AVE высока, хотя никогда не гарантируется на 100%, поскольку ячейка памяти может ссылаться на действительный адрес, когда он повторно используется после сбора заглушки.Случайное выполнение кода является режимом сбоя.Любой результат является чрезмерно уродливым и трудным для диагностики, никогда не позволяйте ему зайти так далеко.
Это вызвано тем, что вы не сохранили ссылку на делегат, который вы передали в собственный код.Или не поддерживая объект, который хранит ссылку, то же самое.Сборщик мусора не может видеть и не знает, что нативный код использует заглушку.Фактически, CLR уничтожает заглушку при получении делегата, и именно так он управляет выделением памяти для заглушек.
Вы должны убедиться, что этого не произойдет.Наиболее часто правильным решением является сохранение ссылки на объект делегата в закрытой переменной static
.Установите значение null
только тогда, когда вы явно указали нативному коду больше не выполнять обратные вызовы.Никогда не устанавливайте его обратно в ноль, это довольно часто.Также добавьте тест, чтобы убедиться, что он равен нулю, прежде чем назначить переменную, если это не так, выведите исключение InvalidOperationException.Если вам нужен дополнительный уровень косвенности, используйте GCHandle.Alloc(Object)
.Тот же рецепт, не вызывайте Free (), пока не узнаете, что это безопасно.