Непонятное поведение фиксированного указателя вне фиксированного оператора.
-
21-08-2019 - |
Вопрос
Может кто-нибудь объяснить мне, почему приведенный ниже код C # не дает сбоя?Почему Visual Studio на самом деле позволяет его скомпилировать?Насколько я понимаю, я получаю фиксированный указатель, но он фиксируется только внутри оператора «fixed».Когда указатель возвращается из функции Foo, можно собрать массив ar.Затем я заставляю GC сделать это, но последовательная запись в память (которая теперь освобождена) не вызывает никаких ошибок.
class Program
{
static unsafe byte* Foo()
{
byte[] ar = new byte[100];
fixed (byte* ptr = ar)
{
return ptr;
}
}
static unsafe void Main(string[] args)
{
byte* ptr = Foo();
GC.Collect();
for (int t = 0;;++t) ptr[t%100] = 0;
}
}
Решение
Эрик прав, но ответ, который вы, вероятно, захотите услышать, заключается в том, что «иногда полезно сохранять адрес за пределами фиксированного оператора».
Может быть, память от этого указателя уже зафиксирована другим фиксированным оператором где-то еще, и имеет смысл ее вернуть?Компилятор не пытается вас угадать и выдать шумные предупреждения.
Тем не менее, я надеюсь, что CodeAnalysis или другие продвинутые инструменты вмешаются здесь, где компилятор позволяет вам отрезать себе ногу.
Другие советы
Тот факт, что память освобождена, не означает, что запись в нее приведет к какой-либо ошибке.Когда сборщик мусора освобождает память, он просто помечает ее как свободную на своей внутренней карте памяти — он не возвращает ее сразу ОС, поэтому она по-прежнему остается подходящей памятью для использования вашим процессом.
Конечно, использование указателя за пределами фиксированного блока является ошибкой. очень плохая идея - не делай этого.