Устранение ошибок и предупреждений в небезопасных конструкциях кода

В этой статье рассматривается следующая диагностика компилятора:

  • CS0193: оператор * или -> должен применяться к указателю
  • CS0196: указатель должен индексироваться только одним значением.
  • CS0208: невозможно взять адрес, получить размер или объявить указатель на управляемый тип ('type')
  • CS0209: тип локальной переменной, объявленной в операторе fixed, должен быть указателем
  • CS0210: необходимо предоставить инициализатор в объявлении или fixed оператореusing.
  • CS0211: невозможно принять адрес заданного выражения
  • CS0212: можно использовать только адрес нефиксированного выражения внутри инициализатора fixed инструкции.
  • CS0213: нельзя использовать инструкцию fixed для получения адреса выражения, которое уже было фиксировано.
  • CS0214: указатели и буферы фиксированного размера могут использоваться только в небезопасном контексте.
  • CS0227: небезопасный код может отображаться только в том случае, если компиляция с помощью /unsafe
  • CS0233: "идентификатор" не имеет предопределенного размера, поэтому sizeof может использоваться только в небезопасном контексте.
  • CS0242: эта операция не определена в указателях void
  • CS0244: Ни 'is' ни 'as' недопустимы для указанных типов указателей
  • CS0254: правая сторона назначения фиксированной инструкции может не быть выражением приведения
  • CS0459: не удается принять адрес локальной переменной только для чтения
  • CS0821: неявно типизированные локальные переменные не могут быть исправлены
  • CS1641: поле буфера фиксированного размера должно иметь описатель размера массива после имени поля
  • CS1642: поля буфера фиксированного размера могут быть только членами структур.
  • CS1656: Невозможно присвоить значение переменной, потому что она является типом переменной только для чтения.
  • CS1663: тип буфера фиксированного размера должен быть одним из следующих типов: bool, byteили shortintlongcharsbyteushortuintulongfloatdouble
  • CS1665: буферы фиксированного размера должны иметь длину больше нуля
  • CS1666: нельзя использовать буферы фиксированного размера, содержащиеся в нефиксированных выражениях. Попробуйте использовать фиксированную инструкцию.
  • CS1708: доступ к буферам фиксированного размера можно получить только через локальные или поля
  • CS1716: не используйте атрибут 'System.Runtime.CompilerServices.FixedBuffer' . Вместо этого используйте модификатор поля fixed.
  • CS1919: небезопасный тип "имя типа" нельзя использовать в создании объекта.
  • CS4004: невозможно await в небезопасном контексте
  • CS7092: фиксированный буфер может иметь только одно измерение.
  • CS8372: не используйте атрибут 'System.Runtime.CompilerServices.FixedBuffer' в свойстве
  • CS8812: не удается преобразовать группу методов "method" в тип указателя без функции "type".
  • CS9049: фиксированное поле не должно быть полем ссылок.
  • CS9123: оператор '&' не должен использоваться для параметров или локальных переменных в асинхронных методах.
  • CS9360: эта операция может использоваться только в небезопасном контексте.
  • CS9361: stackalloc выражение без инициализатора внутри SkipLocalsInit может использоваться только в небезопасном контексте.
  • CS9362: "member" должен использоваться в небезопасном контексте, так как он помечен как "RequiresUnsafe" или "extern"
  • CS9363: "member" должен использоваться в небезопасном контексте, так как он имеет указатели в подписи.
  • CS9364: небезопасный элемент «element» не может переопределить безопасный элемент «element»
  • CS9365: небезопасный член "член" не может неявно реализовать безопасный член "член"
  • CS9366: Небезопасный элемент "член" не может реализовать безопасный элемент "член"
  • CS9367: RequiresUnsafeAttribute нельзя применить к этому символу.
  • CS9368: RequiresUnsafeAttribute действителен только в соответствии с обновленными правилами безопасности памяти.
  • CS9376: Требуется небезопасный контекст для конструктора, помеченного как "RequiresUnsafe" или "extern" для удовлетворения ограничения параметра типа "new()" в "универсальном типе или методе".
  • CS9377: модификатор 'unsafe' не имеет никакого эффекта в соответствии с текущими правилами безопасности памяти.

Операции указателя и отмена ссылок

  • CS0193: оператор *-> должен применяться к указателю
  • CS0196: указатель должен индексироваться только одним значением.
  • CS0242: эта операция не определена в указателях void

Чтобы правильно использовать операции указателя, следуйте правилам разыменования, индексации и арифметическим операциям. Дополнительные сведения см. в разделе "Типы указателей " и указатели функций.

  • * -> Примените оператор только к указателям данных (CS0193). Не используйте эти операторы с неуказательными типами или указателями на функции. В отличие от C/C++, в C# невозможно разыменовать указатели функций.
  • Указатели индекса только с одним значением (CS0196). Многомерное индексирование не поддерживается на указателях.
  • Избегайте операций, которые не определены в указателях void (CS0242). Не инкрементируйте указатель void, так как компилятор не знает размер данных, на которые он указывает.

Типы указателей и управляемые типы

  • CS0208: нельзя взять адрес, узнать размер или объявить указатель на управляемый тип ('тип')
  • CS0233: "идентификатор" не имеет предопределенного размера, поэтому sizeof может использоваться только в небезопасном контексте.

Чтобы работать с указателями и sizeof оператором правильно, используйте неуправляемые типы и правильные контексты. Дополнительные сведения см. в разделе "Неуправляемые типы" и о операторе sizeof.

  • Используйте указатели только с неуправляемыми типами (CS0208). Не объявляйте указатели, не берите адрес и размер управляемых типов. Управляемые типы включают ссылочные типы и структуры, содержащие поля ссылочного типа или свойства.
  • sizeof Используйте оператор в контексте unsafe при работе с типами, размер которых не является константой времени компиляции (CS0233).

Фиксированное использование инструкций

  • CS0209: тип локальной переменной, объявленной в операторе fixed, должен быть типом указателя.
  • CS0210: в объявлении инструкции fixed или using необходимо предоставить инициализатор.
  • CS0211: невозможно принять адрес заданного выражения
  • CS0212: можно использовать только адрес нефиксированного выражения внутри инициализатора фиксированной инструкции.
  • CS0213: нельзя использовать оператор fixed для получения адреса уже фиксированного выражения.
  • CS0254: правая сторона назначения фиксированной инструкции может не быть выражением приведения
  • CS0459: не удается принять адрес локальной переменной только для чтения
  • CS0821: неявно типизированные локальные переменные не могут быть исправлены
  • CS1656: Невозможно присвоить значение переменной, поскольку она имеет тип "только для чтения".

Эти ошибки возникают при неправильном использовании инструкцииfixed. Инструкция fixed предотвращает сборщик мусора от перемещения переменной, которую можно перемещать, и объявляет указатель на эту переменную. Дополнительные сведения см. в разделе "Небезопасный код и указатели".

Чтобы правильно использовать инструкцию fixed , выполните следующие действия.

  • Объявите переменную как тип указателя (CS0209).
  • Укажите инициализатор в объявлении инструкции fixed (CS0210).
  • Используйте адрес только допустимых выражений: поля, локальные переменные и разыменование указателя (CS0211). Не используйте адрес вычисляемых выражений, таких как сумма двух переменных.
  • Используйте оператор address-of для нефиксированных выражений только в инициализаторе fixed инструкции (CS0212).
  • Не используйте инструкцию fixed для уже фиксированных выражений (CS0213). Локальные переменные и параметры в unsafe методе уже расположены на стеке.
  • Не используйте выражения приведения на правой стороне выражения присваивания fixed (CS0254).
  • Не считывайте адрес локальных переменных, которые являются только для чтения (CS0459). Переменные в foreach циклах, using инструкциях и fixed инструкциях доступны только для чтения. Эта ошибка больше не создается текущими версиями компилятора.
  • Используйте явные типы вместо var в инструкциях fixed (CS0821).
  • Не присваивайте переменным в контекстах, доступных только для чтения, таких как foreach циклы, using инструкции или fixed инструкции (CS1656).

Небезопасные требования к контексту

  • CS0214: указатели и буферы фиксированного размера могут использоваться только в небезопасном контексте.
  • CS0227: небезопасный код может использоваться только при компиляции с параметром /unsafe
  • CS0244: ни 'is', ни 'as' не являются допустимыми для типов указателей
  • CS1919: небезопасный тип "имя типа" нельзя использовать в создании объекта
  • CS4004: невозможно await в небезопасном контексте
  • CS9123: оператор '&' не должен использоваться для параметров или локальных переменных в асинхронных методах
  • CS9360: эта операция может использоваться только в небезопасном контексте.
  • CS9361: stackalloc выражение без инициализатора внутри SkipLocalsInit может использоваться только в небезопасном контексте.
  • CS9362: "member" должен использоваться в небезопасном контексте, так как он помечен как "RequiresUnsafe" или "extern"
  • CS9363: "member" должен использоваться в небезопасном контексте, так как он имеет указатели в подписи.
  • CS9376: небезопасный контекст требуется для конструктора 'конструктор', помеченного как 'RequiresUnsafe' или 'extern', чтобы удовлетворить ограничение 'new()' типа параметра 'тип параметра' в 'обобщённый тип или метод'.

Диагностика выполняется при использовании небезопасных конструкций кода без требуемого контекста unsafe, или при попытке выполнить операции, которые запрещены с небезопасными типами. Дополнительные сведения см. в разделе "Небезопасный код и указатели" иключевоеunsafe слово.

  • Пометьте методы, типы или блоки кода, использующие указатели или буферы фиксированного размера с unsafe ключевым словом (CS0214). Компилятору требуется явный небезопасный контекст для любого кода, который работает с типами указателей или полями буфера фиксированного размера.
  • Включите параметр компилятора AllowUnsafeBlocks в параметрах проекта (CS0227). Без этого параметра компилятор отклоняет все unsafe блоки, даже если код является правильным.
  • Не используйте is или as операторы с типами указателей (CS0244). Эти операторы тестирования типов недопустимы для указателей, так как указатели не участвуют в иерархии типов.
  • Не используйте new оператор для создания экземпляров типов указателя (CS1919). Чтобы создать объекты в неуправляемой памяти, используйте взаимодействие для вызова собственных методов, возвращающих указатели.
  • Небезопасный код отделяется от асинхронного кода (CS4004). Компилятор не разрешает await выражения внутри unsafe блока, так как среда выполнения не может гарантировать допустимость указателя между точками приостановки. Создайте отдельные методы для небезопасных операций и вызовите их из асинхронных методов.
  • Не используйте оператор адреса (&) для параметров или локальных переменных в асинхронных методах (CS9123). Переменная может не существовать в стеке, когда асинхронная операция возобновляется после точки приостановки.
  • Помечайте операции, включающие небезопасные конструкции (например, разыменование указателя, взятие адреса или sizeof на неуправляемых типах) с помощью ключевого слова unsafe (CS9360). В соответствии с обновленными правилами безопасности памяти C# 15 компилятор определяет отдельные операции, требующие небезопасного контекста.
  • Используйте ключевое unsafe слово для stackalloc выражений без инициализаторов, когда применён атрибут SkipLocalsInit (CS9361). Без инициализатора выделенная стеком память содержит неинициализированные данные, которые являются небезопасной операцией.
  • Используйте контекст unsafe при вызове членов, помеченных RequiresUnsafe или extern (CS9362), или членов, содержащих указатели в их сигнатурах (CS9363). Компилятор C# 15 отслеживает небезопасное использование члена на сайте вызова, а не только в объявлении.
  • Используйте контекст unsafe, если ограничение new() требует вызова конструктора, помеченного RequiresUnsafe или extern (CS9376). Обобщённый экземпляр вызывает конструктор неявно, поэтому вызов должен происходить в небезопасном контексте.

Небезопасные контракты безопасности членов

  • CS9364: небезопасный элемент "member" не может переопределить безопасный элемент "member"
  • CS9365: небезопасный член "member" не может неявно реализовать безопасный член "member"
  • CS9366: небезопасный член "член" не может реализовать безопасный член "член"
  • CS9367: RequiresUnsafeAttribute нельзя применить к этому символу.
  • CS9368: RequiresUnsafeAttribute действителен только в соответствии с обновленными правилами безопасности памяти.
  • CS9377: модификатор 'unsafe' не имеет никакого эффекта в соответствии с текущими правилами безопасности памяти.

Эти средства диагностики применяют правила контракта безопасности C# 15 для членов, помеченных как небезопасные. Компилятор гарантирует, что небезопасные члены не нарушают ожидания безопасности, установленные базовыми классами и интерфейсами. Дополнительные сведения см. в разделе "Небезопасный код и указатели" иключевоеunsafe слово.

  • Не переопределите безопасный базовый элемент с небезопасным членом (CS9364). Переопределение должно сохранить безопасность контракта базового члена. Если базовый элемент является безопасным, переопределение также должно быть безопасным. Удалите модификатор unsafe или RequiresUnsafeAttribute из переопределяющего элемента, или пометьте базовый элемент как небезопасный.
  • Не реализуйте неявно безопасный элемент интерфейса с использованием небезопасного члена (CS9365). Если тип неявно реализует член интерфейса, вызывающие через интерфейс ожидают безопасной операции. Удалите небезопасное обозначение из реализуемого элемента или используйте явную реализацию интерфейса.
  • Не реализуйте явным образом безопасный элемент интерфейса с небезопасным членом (CS9366). Даже с явной реализацией необходимо сохранить контракт безопасности члена интерфейса.
  • Применяется RequiresUnsafeAttribute только к поддерживаемым типам символов (CS9367). Этот атрибут можно применять к методам, свойствам, событиям, конструкторам и типам, но не ко всем типам символов.
  • Включите обновленные правила безопасности памяти для использования RequiresUnsafeAttribute (CS9368). Этот атрибут является частью модели безопасности памяти C# 15 и не распознается в соответствии с устаревшими правилами. Убедитесь, что проект предназначен для языковой версии, поддерживающей обновленные правила.
  • unsafe Удалите модификатор, если он не имеет эффекта (CS9377). В соответствии с текущими правилами безопасности памяти в определенных контекстах не требуется использование модификатора unsafe. Компилятор предупреждает, когда модификатор не имеет смысла, чтобы можно было очистить ненужные заметки.

Буферы фиксированного размера

  • CS1641: поле буфера фиксированного размера должно иметь описатель размера массива после имени поля
  • CS1642: поля буфера фиксированного размера могут быть только членами структур
  • CS1663: тип буфера фиксированного размера должен быть одним из следующих типов: bool, byteили shortintlongcharsbyteushortuintulongfloatdouble
  • CS1665: буферы фиксированного размера должны иметь длину больше нуля
  • CS1666: нельзя использовать буферы фиксированного размера, содержащиеся в нефиксированных выражениях. Попробуйте использовать фиксированную инструкцию
  • CS1708: доступ к буферам фиксированного размера можно получить только через локальные или поля
  • CS1716: не используйте атрибут 'System.Runtime.CompilerServices.FixedBuffer' . Вместо этого используйте модификатор поля "фиксированный"
  • CS7092: фиксированный буфер может иметь только одно измерение.
  • CS8372: не используйте атрибут 'System.Runtime.CompilerServices.FixedBuffer' в свойстве
  • CS9049: фиксированное поле не должно быть полем ссылок

Эти ошибки возникают при работе с буферами фиксированного размера. Буферы фиксированного размера являются массивами, внедренными непосредственно в структуры, и в основном используются для сценариев взаимодействия. Дополнительные сведения см. в разделе " Буферы фиксированного размера".

Чтобы правильно объявлять и использовать буферы фиксированного размера, выполните приведенные ниже действия.

  • Укажите размер массива после имени поля с помощью положительной целочисленной константы (CS1641, CS1665).
  • Объявляйте буферы фиксированного размера только в структуры, а не в классах (CS1642). Используйте обычный массив, если требуется поле в классе.
  • Используйте один из поддерживаемых типов элементов: bool, byteshortintlongcharsbyteushortuintulongfloatилиdouble (CS1663).
  • Используйте конструкцию fixed, чтобы закрепить содержащую структуру перед доступом к буферу (CS1666).
  • Доступ к буферам фиксированного размера только через локальные или поля, а не через промежуточные выражения (CS1708).
  • fixed Используйте модификатор полей вместо атрибута System.Runtime.CompilerServices.FixedBuffer (CS1716). Не применяйте этот атрибут к свойствам (CS8372).
  • Объявите фиксированные буферы только с одним измерением (CS7092). Многомерные фиксированные буферы не поддерживаются.
  • Не объявляйте буферы фиксированного размера как ref поля (CS9049). Буферы фиксированного размера должны быть полями значений.

Указатели функций

  • CS8812: не удается преобразовать группу методов "method" в тип указателя без функции "type".

Чтобы получить указатель функции, используйте оператор адреса с явным приведением типа указателя функции. Не используйте оператор получения адреса & для назначения групп методов к void* или другим типам, не являющимся указателями на функции. Дополнительные сведения см. в указателях функций.