Question

Quelqu'un peut-il donner un exemple d'un bon moment pour utiliser réellement "non sécurisé"? et " fixe " en code C #? J'ai déjà joué avec, mais je ne l'ai jamais vraiment utilisé.

Considérez ce code ...

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

comparé à simplement utiliser ...

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

Le second est le code trouvé dans le .NET Framework, le premier est une partie du code copié à partir du site Web de Microsoft, http://msdn.microsoft.com/en-us/library/28k1s2k6 (VS.80) .aspx .

La structure Array.Copy () intégrée est considérablement plus rapide que l’utilisation de code non sécurisé. Cela pourrait simplement être dû au fait que le second est mieux écrit et que le premier n’est qu’un exemple, mais de quel genre de situation auriez-vous vraiment besoin pour utiliser un code Unsafe / Fixed? Ou bien ce pauvre développeur web joue-t-il avec quelque chose au-dessus de sa tête?

Était-ce utile?

La solution

C’est utile pour interopérer avec du code non managé. Tous les pointeurs transmis aux fonctions non gérées doivent être corrigés (autrement dit, épinglés) pour empêcher le récupérateur de mémoire de déplacer la mémoire sous-jacente.

Si vous utilisez P / Invoke, le marshaller par défaut épinglera des objets pour vous. Il est parfois nécessaire d’effectuer un marshalling personnalisé et parfois d’épingler un objet plus longtemps que la durée d’un seul appel P / Invoke.

Autres conseils

J'ai utilisé des blocs non sécurisés pour manipuler des données Bitmap. L'accès au pointeur brut est nettement plus rapide que SetPixel / GetPixel.

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

" fixe " et " unsafe " est généralement utilisé lors d'interopérabilité ou lorsque des performances supplémentaires sont requises. C'est à dire. String.CopyTo () utilise unsafe et corrigé dans son implémentation.

comportement du style reinterpret_cast

Si vous manipulez un peu, cela peut être incroyablement utile

de nombreuses implémentations de hashcode haute performance utilisent UInt32 pour la valeur de hachage (cela simplifie les décalages). Comme .Net nécessite Int32 pour la méthode, vous souhaitez convertir rapidement l'uint en int. Etant donné que la valeur réelle n’importe pas, c’est seulement que tous les bits de la valeur sont préservés qu’une réinterprétation est souhaitée.

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

Notez que le nom est calqué sur le BitConverter.DoubleToInt64Inbits

Poursuivant dans la veine du hachage, convertir une structure basée sur une pile en un octet * permet d’utiliser facilement les fonctions de hachage par octet:

// 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);
}

unsafe aussi (à partir de 2.0) vous permet d’utiliser stackalloc. Cela peut être très utile dans les situations de hautes performances où un petit tableau de longueur variable tel qu'un espace temporaire est nécessaire.

Toutes ces utilisations sont clairement définies dans la zone "uniquement si votre application a réellement besoin de la performance" et sont donc inappropriées dans le cadre d'une utilisation générale, mais vous en avez parfois vraiment besoin.

fixed est nécessaire lorsque vous souhaitez interagir avec une fonction non gérée utile (il y en a beaucoup) qui prend des tableaux ou des chaînes de style c. En tant que tel, ce n’est pas seulement pour des raisons de performance, mais aussi de correction lors de scénarios interop.

Unsafe est utile, par exemple, pour extraire rapidement des données de pixels d’une image à l’aide de LockBits. L'amélioration des performances par rapport à l'utilisation de l'API gérée est de plusieurs ordres de grandeur.

Nous devions utiliser un corrigé lorsqu'une adresse est transmise à une ancienne DLL C. Étant donné que la DLL conservait un pointeur interne sur les appels de fonction, l'enfer se déchaînerait si le GC compressait le tas et le déplaçait.

Je crois que le code non sécurisé est utilisé si vous souhaitez accéder à quelque chose en dehors du runtime .NET, c'est-à-dire. ce n'est pas du code géré (pas de récupération de place, etc.). Cela inclut les appels bruts à l’API Windows et à tout ce jazz.

Cela me dit que les concepteurs du framework .NET ont bien couvert l'espace du problème, en s'assurant que le " code géré " environnement peut faire tout ce qu'une approche traditionnelle (par exemple, C ++) peut faire avec son code / pointeurs non sécurisés. Dans le cas contraire, les fonctionnalités non sécurisées / fixes sont disponibles si vous en avez besoin. Je suis sûr que quelqu'un a un exemple où un code non sécurisé est nécessaire, mais cela semble rare dans la pratique - ce qui est plutôt le problème, n'est-ce pas? :)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top