Непонятное поведение фиксированного указателя вне фиксированного оператора - PullRequest
0 голосов
/ 14 мая 2009

Может кто-нибудь объяснить мне, почему приведенный ниже код C # не падает? Почему Visual Studio на самом деле позволяет скомпилировать его? Насколько я понимаю, я получаю фиксированный указатель, но он фиксируется только в «фиксированной» инструкции. Когда указатель возвращается из функции '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;
    }
}

Ответы [ 2 ]

1 голос
/ 14 мая 2009

Эрик прав, но ответ, который вы, вероятно, хотите услышать, заключается в том, что «иногда полезно сохранить адрес вне фиксированного оператора».

Может быть, память из этого указателя уже зафиксирована другим фиксированным оператором где-то еще, и имеет смысл вернуть его? Компилятор не пытается угадать вас и выдавать шумные предупреждения.

Тем не менее, я надеюсь, что CodeAnalysis или другие продвинутые инструменты появятся здесь, где компилятор позволяет вам отрезать себе ногу.

1 голос
/ 14 мая 2009

Тот факт, что память освобождена, не означает, что запись в нее может вызвать ошибку любого рода. Когда сборщик мусора освобождает память, он просто помечает ее как свободную на своей внутренней карте памяти - он не сразу возвращает ее ОС, поэтому он все еще является допустимой памятью для вашего процесса.

Конечно, использование указателя вне фиксированного блока для него - очень плохая идея - не делайте этого.

...