Pergunta

Alguém pode dar um exemplo de um bom momento para realmente usar "inseguro" e "fixo" no código C #? Eu joguei com ele antes, mas nunca realmente encontrei um bom uso para ele.

Considere este código ...

fixed (byte* pSrc = src, pDst = dst) {
    //Code that copies the bytes in a loop
}

em comparação com simplesmente usando ...

Array.Copy(source, target, source.Length);

O segundo é o código encontrado no .NET Framework, a primeira parte do código copiado do site da Microsoft, http://msdn.microsoft.com/en-us/library/28k1s2k6 (VS.80) .aspx .

O construído em Array.Copy () é dramaticamente mais rápido do que usando o código inseguro. Este poder apenas porque o segundo é apenas melhor escrito e o primeiro é apenas um exemplo, mas que tipos de situações que você realmente precisa mesmo de usar / Código fixo inseguro para alguma coisa? Ou é este pobre desenvolvedor web mexer com algo acima de sua cabeça?

Foi útil?

Solução

É útil para interoperabilidade com código não gerenciado. Os ponteiros passados ??para funções não gerenciadas precisam ser corrigidos (aka. Presa) para evitar que o coletor de lixo de realocar a memória subjacente.

Se você estiver usando P / Invoke, então o marshaller padrão irá fixar objetos para você. Às vezes é necessário realizar triagem costume, e às vezes é necessário fixar um objeto por mais tempo do que a duração de uma única chamada P / Invoke.

Outras dicas

Eu usei inseguras-blocos para manipular Bitmap-dados. ponteiro de acesso Raw é significativamente mais rápido do que SetPixel / GetPixel.

unsafe
{
    BitmapData bmData = bm.LockBits(...)
    byte *bits = (byte*)pixels.ToPointer();
    // Do stuff with bits
}

"fixo" e "inseguro" é normalmente usado quando fazendo interoperabilidade, ou quando é necessária desempenho extra. Ie. String.CopyTo () usa inseguro e fixo na sua implementação.

comportamento estilo reinterpret_cast

Se você está pouco manipular, então isso pode ser extremamente útil

muitas implementações hashcode alto desempenho usar UInt32 para o valor de hash (isso torna as mudanças mais simples). Desde .Net requer Int32 para o método que você deseja converter rapidamente o uint para um int. Uma vez que não importa o que o valor real é, apenas que todos os bits no valor são preservadas um elenco reinterpretar é desejada.

public static unsafe int UInt32ToInt32Bits(uint x)
{
    return *((int*)(void*)&x);
}

Note que a nomeação é modelado nas BitConverter.DoubleToInt64Bits

Continuando na veia hashing, convertendo um struct baseado em pilha em um byte * permite o fácil uso de per funções hash bytes:

// from the Jenkins one at a time hash function
private static unsafe void Hash(byte* data, int len, ref uint hash)
{
    for (int i = 0; i < len; i++)
    {
        hash += data[i];
        hash += (hash << 10);
        hash ^= (hash >> 6);
    }
}

public unsafe static void HashCombine(ref uint sofar, long data)
{
    byte* dataBytes = (byte*)(void*)&data;
    AddToHash(dataBytes, sizeof(long), ref sofar);
}

inseguro também (de 2,0 em diante) permite que você use stackalloc. Isto pode ser muito útil em situações de alto desempenho onde é necessária alguma variedade pequena de comprimento variável como espaço temporário.

Todos estes usos seria firmemente no 'apenas se o aplicativo realmente precisa do desempenho e, portanto, são inadequadas de uso geral, mas às vezes você realmente precisa fazer isso.

fixo é necessário para quando você deseja interoperabilidade com alguma função não gerenciada útil (há muitos) que leva matrizes ou seqüências de c-estilo. Como tal, não é apenas por motivos de desempenho, mas os de correção quando em cenários de interoperabilidade.

inseguro é útil para (por exemplo) dados de pixel sair de uma imagem rapidamente usando LockBits. A melhoria de desempenho ao longo de fazer isso usando a API gerenciada é várias ordens de magnitude.

Nós tivemos que usar um fixo quando um endereço é passada para um legado C DLL. Desde que a DLL mantém um ponteiro interno através de chamadas de função, todo o inferno iria quebrar solto se o GC compactado pilha e outras coisas movimentados.

Eu acredito código inseguro é usado se você deseja acessar algo fora do tempo de execução .NET, ie. ele não é o código gerenciado (sem coleta de lixo e assim por diante). Isso inclui chamadas matérias para a API do Windows e todo esse jazz.

Isto diz-me os projetistas do framework .NET fez um bom trabalho de cobrir o espaço do problema - de garantir o meio ambiente "código gerenciado" pode fazer tudo o que uma abordagem tradicional (por exemplo, C ++) pode fazer com o seu código inseguro / ponteiros. No caso, não pode, as características inseguras / fixo estão lá se você precisar deles. Tenho certeza de que alguém tem um exemplo onde é necessário código inseguro, mas parece raro na prática - que é um pouco o ponto, não é? :)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top