Resolver erros e avisos em construções de código não seguras

Este artigo cobre os seguintes diagnósticos do compilador:

  • CS0193: O operador * ou -> deve ser aplicado a um ponteiro
  • CS0196: Um ponteiro deve ser indexado por apenas um valor
  • CS0208: Não é possível obter o endereço, obter o tamanho ou declarar um ponteiro para um tipo gerenciado ('tipo')
  • CS0209: O tipo de local declarado numa fixed instrução deve ser um tipo de ponteiro
  • CS0210: Deve fornecer um inicializador numa declaração fixed ou using
  • CS0211: Não é possível tomar o endereço da expressão dada
  • CS0212: Só pode tomar o endereço de uma expressão não fixa dentro de um fixed inicializador de instruções
  • CS0213: Não pode usar a fixed instrução para tomar o endereço de uma expressão já fixa
  • CS0214: Ponteiros e buffers de tamanho fixo só podem ser usados em um contexto inseguro
  • CS0227: Código inseguro só pode aparecer se compilar com /unsafe
  • CS0233: 'identificador' não tem um tamanho predefinido, portanto, sizeof só pode ser usado em um contexto inseguro
  • CS0242: A operação em questão é indefinida em ponteiros vazios
  • CS0244: Nem 'is' nem 'as' são válidos em tipos de ponteiro
  • CS0254: O lado direito de uma atribuição de instrução fixa pode não ser uma expressão de elenco
  • CS0459: Não é possível tomar o endereço de uma variável local somente leitura
  • CS0821: Variáveis locais implícitamente tipadas não podem ser fixas
  • CS1641: Um campo de buffer de tamanho fixo deve ter o especificador de tamanho de matriz após o nome do campo
  • CS1642: Campos de buffer de tamanho fixo podem ser apenas membros de structs
  • CS1656: Não é possível atribuir a 'variável' porque é uma 'variável de tipo somente leitura'
  • CS1663: O tipo de buffer de tamanho fixo deve ser um dos seguintes: bool, byte, short, int, long, charsbyte, ushortuintulongfloat, ou double
  • CS1664: Buffer de tamanho fixo com comprimento 'length' e do tipo 'type' é demasiado grande
  • CS1665: Buffers de tamanho fixo devem ter um comprimento maior que zero
  • CS1666: Não é possível usar buffers de tamanho fixo contidos em expressões não fixas. Tente usar a instrução fixa.
  • CS1708: Buffers de tamanho fixo só podem ser acessados através de locais ou campos
  • CS1716: Não use o atributo 'System.Runtime.CompilerServices.FixedBuffer'. Em vez disso, use o modificador de campo 'fixo'.
  • CS1919:O tipo inseguro 'nome do tipo' não pode ser usado na criação de objetos
  • CS4004: Não é possível await em um contexto inseguro
  • CS7092: Um buffer fixo pode ter apenas uma dimensão.
  • CS8372: Não use o atributo 'System.Runtime.CompilerServices.FixedBuffer' numa propriedade
  • CS8385: A expressão dada não pode ser usada numa afirmação fixa
  • CS8500: Isto obtém o endereço de, o tamanho de ou declara um ponteiro para um tipo gerenciado ('tipo')
  • CS8812: Não é possível converter o grupo de métodos 'método' para o tipo de ponteiro 'tipo' não funcional.
  • CS9049: Um campo fixo não pode ser um campo de referência.
  • CS9123: O operador '&' não deve ser usado em parâmetros ou variáveis locais em métodos assíncronos.
  • CS9360: Esta operação só pode ser usada em contextos inseguros
  • CS9361: stackalloc a expressão sem inicializador interno SkipLocalsInit só pode ser usada em contextos inseguros
  • CS9362: 'member' deve ser usado num contexto inseguro porque está marcado como 'RequiresUnsafe' ou 'extern'
  • CS9363: 'member' deve ser usado num contexto inseguro porque tem ponteiros na sua assinatura
  • CS9364: O membro inseguro 'membro' não pode substituir o membro seguro 'membro'
  • CS9365: Membro 'membro' inseguro não pode implementar implicitamente membro 'membro' seguro
  • CS9366:Membro inseguro 'membro' não pode implementar membro seguro 'membro'
  • CS9367: RequiresUnsafeAttribute não pode ser aplicado a este símbolo.
  • CS9368: RequiresUnsafeAttribute só é válido ao abrigo das regras de segurança de memória atualizadas.
  • CS9376: É necessário um contexto inseguro para que o construtor 'constructor' seja marcado como 'RequiresUnsafe' ou 'extern' para satisfazer a restrição 'new()' do parâmetro de tipo 'parâmetro de tipo' em um 'tipo ou método' genérico
  • CS9377:O modificador 'unsafe' não tem qualquer efeito aqui segundo as regras atuais de segurança de memória.
  • CS9379: Não use 'RequiresUnsafeAttribute' na fonte; use o modificador 'unsafe' em vez disso.
  • CS9388:O modificador 'safe' só pode ser usado em membros 'extern' que não estejam marcados 'unsafe'.
  • CS9389: o membro 'extern' tem de estar marcado como 'unsafe' ou 'safe'.
  • CS9390: Ambas as declarações parciais dos membros devem estar marcadas como 'safe' ou nenhuma pode ser marcada 'safe'

Operações de ponteiro e desreferenciação

  • CS0193: O operador * ou -> deve ser aplicado a um ponteiro
  • CS0196: Um ponteiro deve ser indexado por apenas um valor
  • CS0242: A operação em questão é indefinida em ponteiros vazios

Para usar operações de ponteiro corretamente, siga as regras para operações de desreferenciação, indexação e aritmética. Para obter mais informações, consulte Tipos de ponteiro e Ponteiros de função.

  • Aplique o operador * ou -> aos ponteiros de dados somente (CS0193). Não use esses operadores com tipos que não sejam pointers ou ponteiros de funções. Ao contrário do C/C++, não se podem desreferenciar ponteiros de função em C#.
  • Ponteiros de índice com apenas um valor (CS0196). A indexação multidimensional não é suportada em ponteiros.
  • Evite operações indefinidas em ponteiros vazios (CS0242). Por exemplo, não incremente um ponteiro void porque o compilador não sabe o tamanho dos dados para os quais está a apontar.

Tipos de ponteiro e tipos gerenciados

  • CS0208: Não é possível obter o endereço, obter o tamanho ou declarar um ponteiro para um tipo gerenciado ('tipo')
  • CS0233: 'identificador' não tem um tamanho predefinido, portanto, sizeof só pode ser usado em um contexto inseguro
  • CS8500:Este toma o endereço de, obtém o tamanho de, ou declara um ponteiro para um tipo gerido ('tipo')

Para trabalhar com ponteiros e o sizeof operador corretamente, use tipos não gerenciados e contextos adequados. Para obter mais informações, consulte Tipos não gerenciados e o sizeof operador.

  • Use ponteiros somente com tipos não gerenciados (CS0208). Não obtenha o endereço de, o tamanho de, ou declare ponteiros para tipos gerenciados. Os tipos gerenciados incluem tipos de referência e estruturas que contêm campos ou propriedades de tipo de referência.
  • Use o sizeof operador dentro de um unsafe contexto ao trabalhar com tipos cujo tamanho não é uma constante de tempo de compilação (CS0233).
  • Evite obter o endereço de, obter o tamanho de ou declarar um ponteiro para um tipo gerido (CS8500). Este aviso (nível 4) é ativado quando o compilador deteta operações de ponteiro em tipos geridos. Um tipo gerido é qualquer tipo de referência, ou qualquer struct que contenha um tipo de referência como campo ou propriedade. Para obter mais informações, consulte Tipos não gerenciados.

Uso fixo da instrução

  • CS0209: O tipo de local declarado numa instrução fixa deve ser um tipo de ponteiro
  • CS0210: Você deve fornecer um inicializador em uma declaração fixa ou using de instrução
  • CS0211: Não é possível tomar o endereço da expressão dada
  • CS0212: Você só pode pegar o endereço de uma expressão não fixa dentro de um inicializador de instrução fixa
  • CS0213: Não é possível usar a instrução fixa para obter o endereço de uma expressão já fixa
  • CS0254: A parte direita de uma atribuição numa instrução 'fixed' não pode ser uma expressão de conversão
  • CS0459: Não é possível obter o endereço de uma variável local somente leitura
  • CS0821: Variáveis locais implícitamente tipadas não podem ser fixas
  • CS1656: Não pode atribuir à 'variável' porque é um 'tipo de variável de leitura apenas'
  • CS8385: A expressão dada não pode ser usada numa afirmação fixa

Esses erros ocorrem quando você usa a fixed instrução incorretamente. A fixed instrução impede que o coletor de lixo realoque uma variável móvel e declara um ponteiro para essa variável. Para mais informações, consulte Código e ponteiros inseguros.

Para usar a fixed instrução corretamente:

  • Declare a variável como um tipo de ponteiro (CS0209).
  • Forneça um inicializador na declaração da instrução fixed (CS0210).
  • Obtenha o endereço apenas de expressões válidas: campos, variáveis locais e desreferência de ponteiro (CS0211). Não tome o endereço de expressões computadas como a soma de duas variáveis.
  • Use o operador address-of em expressões não fixadas somente dentro do fixed inicializador de instrução (CS0212).
  • Não use uma fixed instrução em expressões já resolvidas (CS0213). Variáveis locais e parâmetros em um unsafe método já estão definidos na pilha.
  • Não utilize expressões de conversão no lado direito de uma declaração de atribuição (fixed).
  • Não obtenha o endereço de variáveis locais de leitura apenas (CS0459). As variáveis em foreach loops, using instruções e fixed instruções são somente leitura. Este erro já não é produzido pelas versões atuais do compilador.
  • Use tipos explícitos em vez de var nas instruções fixed (CS0821).
  • Não atribua a variáveis em contextos de apenas leitura, como foreach loops, using instruções ou fixed instruções (CS1656).
  • Utilize apenas expressões que permitam a fixação numa instrução fixed (CS8385). A expressão deve ser uma variável endereçável, uma cadeia de caracteres ou um tipo que implemente um método adequado GetPinnableReference .

Requisitos de contexto inseguro

  • CS0214: Ponteiros e buffers de tamanho fixo só podem ser usados em um contexto inseguro
  • CS0227: Código não seguro só pode aparecer se compilar com /unsafe
  • CS0244:Nem 'is' nem 'as' são válidos para tipos de ponteiros
  • CS1919: O tipo não seguro 'nome do tipo' não pode ser usado na criação de objetos
  • CS4004: Não pode await num contexto inseguro
  • CS9123: O operador '&' não deve ser usado em parâmetros ou variáveis locais em métodos assíncronos
  • CS9360: Esta operação só pode ser usada em contextos inseguros
  • CS9361: stackalloc a expressão sem inicializador interno SkipLocalsInit só pode ser usada em contextos inseguros
  • CS9362: 'member' deve ser usado num contexto inseguro porque está marcado como 'RequiresUnsafe' ou 'extern'
  • CS9363: 'member' deve ser usado num contexto inseguro porque tem ponteiros na sua assinatura
  • CS9376: É necessário um contexto inseguro para que o construtor 'constructor', marcado como 'RequiresUnsafe' ou 'extern', satisfaça a restrição 'new()' do parâmetro de tipo 'parâmetro de tipo' em 'tipo ou método' genérico

Estes diagnósticos ocorrem quando se usam construções de código inseguras sem o contexto necessário unsafe , ou quando se tentam operações que não são permitidas com tipos inseguros. Para mais informações, veja Código e ponteiros inseguros e a unsafe palavra-chave.

  • Marque métodos, tipos ou blocos de código que usam ponteiros ou buffers de tamanho fixo com a unsafe palavra-chave (CS0214). O compilador requer um contexto explícito e inseguro para qualquer código que funcione com tipos de ponteiro ou campos de buffer de tamanho fixo.
  • Ativa a opção do compilador AllowUnsafeBlocks nas definições do teu projeto (CS0227). Sem esta opção, o compilador rejeita todos unsafe os blocos mesmo que o código esteja correto.
  • Não use os operadores is ou as com tipos de ponteiro (CS0244). Estes operadores de teste de tipos não são válidos para apontadores porque estes não participam na hierarquia de tipos.
  • Não use o operador new para criar instâncias do tipo de ponteiro (CS1919). Para criar objetos na memória não gerida, use interop para chamar métodos nativos que retornam ponteiros.
  • Mantenha o código não seguro separado do código assíncrono (CS4004). O compilador não permite as expressões await num bloco unsafe porque o tempo de execução não pode garantir a validade do ponteiro entre pontos de suspensão. Crie métodos separados para operações inseguras e chame-os a partir de métodos assíncronos.
  • Não use o operador de endereço (&) em parâmetros ou variáveis locais em métodos assíncronos (CS9123). A variável pode não existir na pilha quando a operação assíncrona retoma após um ponto de suspensão.
  • Marque operações que envolvam construções inseguras (como desreferenciação de ponteiros, address-of, ou sizeof em tipos não geridos) com a unsafe palavra-chave (CS9360). De acordo com as regras de segurança de memória atualizadas do C# 15, o compilador identifica operações individuais que requerem um contexto inseguro.
  • Use a palavra-chave unsafe para expressões stackalloc sem inicializadores quando o atributo SkipLocalsInit é aplicado (CS9361). Sem um inicializador, a memória alocada na pilha contém dados não inicializados, o que é uma operação insegura.
  • Use um unsafe contexto ao chamar membros marcados com RequiresUnsafe ou extern (CS9362), ou membros com ponteiros nas suas assinaturas (CS9363). O compilador C#15 acompanha o uso inseguro dos membros no local da chamada, não apenas na declaração.
  • Use um unsafe contexto quando uma new() restrição exige chamar um construtor marcado com RequiresUnsafe ou extern (CS9376). A instanciação genérica chama o construtor implicitamente, pelo que o contexto de chamada deve ser inseguro.

Contratos de segurança para membros inseguros

  • CS9364: Membro inseguro 'membro' não pode sobrepor membro seguro 'membro'
  • CS9365: Membro inseguro 'membro' não pode implementar implicitamente um membro seguro
  • CS9366:Elemento inseguro 'membro' não pode implementar elemento seguro 'membro'
  • CS9367: RequiresUnsafeAttribute não pode ser aplicado a este símbolo.
  • CS9368: RequiresUnsafeAttribute só é válido ao abrigo das regras de segurança de memória atualizadas.
  • CS9377:O modificador 'unsafe' não tem qualquer efeito aqui segundo as regras atuais de segurança de memória.
  • CS9379: Não use 'RequiresUnsafeAttribute' na fonte; use o modificador 'unsafe' em vez disso.
  • CS9388:O modificador 'safe' só pode ser usado em membros 'extern' que não estejam marcados 'unsafe'.
  • CS9389: 'extern' o membro deve estar marcado 'unsafe' ou 'safe'.
  • CS9390: Ambas as declarações parciais dos membros devem estar marcadas como 'safe' ou nenhuma pode ser marcada 'safe'

Estes diagnósticos aplicam as regras do contrato de segurança C#15 para membros marcados como inseguros. O compilador garante que membros inseguros não violam as expectativas de segurança estabelecidas pelas classes base e interfaces. Para mais informações, veja Código e ponteiros inseguros e a unsafe palavra-chave.

  • Não substitua um membro da base segura com um membro inseguro (CS9364). Uma sobreposição deve preservar o contrato de segurança do membro da base. Se o elemento base estiver seguro, a sobreposição também deve ser segura. Remova o unsafe modificador ou RequiresUnsafeAttribute do elemento sobreposto, ou marque o elemento base como inseguro.
  • Não implemente implicitamente um membro de interface segura com um membro não seguro (CS9365). Quando um tipo implementa implicitamente um membro da interface, os chamadores através da interface esperam uma operação segura. Remover a designação insegura do membro implementador, ou usar uma implementação explícita da interface.
  • Não implemente explicitamente um membro de interface segura com um membro não seguro (CS9366). Mesmo com implementação explícita, o contrato de segurança do elemento da interface deve ser preservado.
  • Aplique RequiresUnsafeAttribute apenas aos tipos de símbolos suportados (CS9367). Este atributo pode ser aplicado a métodos, propriedades, eventos, construtores e tipos, mas nem todos os tipos de símbolos o suportam.
  • Ative as regras atualizadas de segurança de memória para usar RequiresUnsafeAttribute (CS9368). Esta característica faz parte do modelo refinado de segurança de memória do C# 15 e não é reconhecida segundo regras legadas. Assegure que o seu projeto tem como alvo uma versão linguística que suporte as regras atualizadas.
  • Remova o unsafe modificador quando não tiver efeito (CS9377). Segundo as regras atuais de segurança de memória, certos contextos não requerem nem beneficiam do unsafe modificador. O compilador avisa quando o modificador não tem significado para que possas limpar anotações desnecessárias.
  • Use o unsafe modificador diretamente na declaração de membro em vez de aplicar RequiresUnsafeAttribute na fonte (CS9379). O atributo destina-se apenas à representação de metadados; No código-fonte, a unsafe palavra-chave é o mecanismo correto.
  • Aplique o modificador safe apenas aos membros extern que ainda não estejam marcados com unsafe (CS9388). O safe modificador exclui explicitamente um membro externo da suposição predeterminada de insegurança para declarações externas.
  • Marque cada extern membro como sendo unsafe ou safe (CS9389). De acordo com as regras atualizadas de segurança de memória, os membros externos devem declarar explicitamente o seu contrato de segurança porque o compilador não pode verificar a implementação.
  • Assegure que ambas as declarações parciais dos membros concordam com o safe modificador (CS9390). Se uma declaração parcial estiver marcada safe, a outra também deve ser marcada safe para manter um contrato de segurança consistente.

Buffers de tamanho fixo

  • CS1641: Um campo de buffer de tamanho fixo deve ter o especificador de tamanho de matriz após o nome do campo
  • CS1642: Campos de buffer de tamanho fixo só podem ser membros de structs
  • CS1663: O tipo de buffer de tamanho fixo deve ser um dos seguintes: bool, byte, short, intlong, , char, sbyte, ushortuintulongfloat ou double
  • CS1664: Buffer de tamanho fixo com comprimento 'length' e do tipo 'type' é demasiado grande
  • CS1665: Buffers de tamanho fixo devem ter um comprimento maior que zero
  • CS1666:Não pode usar buffers de tamanho fixo contidos em expressões não fixas. Tenta usar a instrução fixa.
  • CS1708: Buffers de tamanho fixo só podem ser acessados através de locais ou campos
  • CS1716: Não use o atributo 'System.Runtime.CompilerServices.FixedBuffer'. Use antes o modificador de campo 'fixo'.
  • CS7092: Um buffer fixo pode ter apenas uma dimensão.
  • CS8372: Não use o atributo 'System.Runtime.CompilerServices.FixedBuffer' numa propriedade
  • CS9049: Um campo fixo não pode ser um campo de referência.

Esses erros ocorrem quando você trabalha com buffers de tamanho fixo. Os buffers de tamanho fixo são matrizes incorporadas diretamente em structs e são usados principalmente para cenários de interoperabilidade. Para obter mais informações, consulte Buffers de tamanho fixo.

Para declarar e usar buffers de tamanho fixo corretamente:

  • Especifique o tamanho da matriz após o nome do campo usando uma constante inteira positiva (CS1641, CS1665). O tamanho total do buffer (número de elementos multiplicado pelo tamanho dos elementos) não deve exceder 2^31 bytes (CS1664).
  • Declare buffers de tamanho fixo somente em structs, não em classes (CS1642). Use uma matriz regular se precisar do campo em uma classe.
  • Use um dos tipos de elementos suportados: bool, byte, short, int, long, char, sbyte, ushort, uintulongfloatou double (CS1663).
  • Use uma fixed instrução para fixar o struct que contém antes de acessar o buffer (CS1666).
  • Acesse buffers de tamanho fixo somente por meio de locais ou campos, não por meio de expressões intermediárias (CS1708).
  • Use o fixed modificador de campo em vez do System.Runtime.CompilerServices.FixedBuffer atributo (CS1716). Também não aplique este atributo a propriedades (CS8372).
  • Declarar buffers fixos com apenas uma dimensão (CS7092). Buffers fixos multidimensionais não são suportados.
  • Não declare buffers de tamanho fixo como campos ref (CS9049). Buffers de tamanho fixo devem ser campos de valor.

Ponteiros de função

  • CS8812: Não é possível converter o grupo de métodos 'método' para o tipo de ponteiro 'tipo' não funcional.

Para obter um ponteiro de função, use o operador de endereço com um casting explícito do tipo de apontador de função. Não use o operador &address-of para atribuir grupos de métodos a void* ou a outros tipos de ponteiro que não sejam de função. Para obter mais informações, consulte Ponteiros de função.