2010-03-22 3 views
31

Quelles sont les conséquences (positives/négatives) de l'utilisation du mot-clé non sécurisé dans C# pour utiliser des pointeurs? Par exemple, que deviennent les garbage collection, quels sont les gains/pertes de performance, quels sont les gains/pertes de performance par rapport aux autres langues, la gestion manuelle de la mémoire, quels sont les dangers, dans quelle situation est-il vraiment justifié d'utiliser ce langage? fonctionnalité, est-il plus long à compiler ...?Gestion de la mémoire C#: mots-clés et pointeurs non sécurisés

Répondre

25

Comme déjà mentionné par Conrad, il existe certaines situations où un accès non sécurisé à la mémoire en C# est utile. Il n'y a pas autant d'entre eux, mais il y a quelques-uns:

  • avec Bitmap Manipuler est presque un exemple typique où vous avez besoin de performances supplémentaires que vous pouvez obtenir en utilisant unsafe.

  • interopérabilité avec ancienne API (comme WinAPI ou natif DLL C/C++) est un autre domaine où unsafe peut être très utile - par exemple, vous pouvez appeler une fonction qui prend/renvoie un pointeur non géré.

D'autre part, vous pouvez écrire la plupart des choses en utilisant Marshall class, qui cache un grand nombre des opérations dangereuses à l'intérieur des appels de méthode. Ce sera un peu plus lent, mais il est une option si vous voulez éviter d'utiliser unsafe (ou si vous utilisez VB.NET qui n'a pas unsafe)

Conséquences positives: Ainsi, les principaux les conséquences positives de l'existence de unsafe en C# est que vous pouvez écrire du code plus facilement (interopérabilité) et écrire du code plus efficacement (manipuler avec bitmap ou peut-être de lourds calculs numériques en utilisant des tableaux - bien que je ne sois pas sûr à propos du second).

conséquences négatives: Bien sûr, il y a un certain prix que vous devez payer pour utiliser unsafe:

  • code non vérifiable: C# code qui est écrit en utilisant les unsafe caractéristiques devient non -verifiable, ce qui signifie que votre code pourrait compromettre l'exécution de quelque façon que ce soit. Ce n'est pas un gros problème dans un scénario full-trust (par exemple, application de bureau non restreinte) - vous n'avez tout simplement pas toutes les bonnes garanties .NET CLR. Toutefois, vous ne pouvez pas exécuter l'application dans un environnement restreint, tel qu'un hébergement Web public, Silverlight ou une approbation partielle (par exemple une application exécutée à partir du réseau).

  • Garbage collector doit également être prudent lorsque vous utilisez unsafe. GC est généralement autorisé à déplacer des objets sur le tas géré (pour conserver la mémoire défragmentée). Lorsque vous prenez un pointeur vers un objet, vous devez utiliser le mot-clé fixed pour indiquer au GC qu'il ne peut pas déplacer l'objet jusqu'à la fin (ce qui peut probablement affecter les performances de la récupération de place - mais bien sûr, selon le scénario exact) .

Je pense que si C# n'a pas eu à interopérer avec le code ancien, il ne serait probablement pas soutenir unsafe (et projets de recherche comme Singularity qui tentent de créer un système d'exploitation plus vérifiable en fonction des langues gérées désavouer définitivement usnsafe code). Cependant, dans le monde réel, unsafe est utile dans certains cas (rares).

4

Pour citer Professional C# 2008:

« Les deux principales raisons pour l'utilisation de pointeurs sont:

  1. compability arrière - Malgré toutes les facilités offertes par le .NET- runtime il est toujours possible de appeler les fonctions API Windows natives, et pour certaines opérations cela peut être le seul moyen d'accomplir votre tâche.Ces fonctions API sont généralement écrites en C et nécessitent souvent des pointeurs en tant que paramètres. Cependant, dans de nombreux cas, il est possible d'écrire la déclaration DllImport d'une manière que évite l'utilisation de pointeurs; Par exemple, en utilisant la classe System.IntPtr.
  2. Performance - Dans les cas où la vitesse est de , le pointeur peut fournir une route pour une performance optimisée. Si vous savez ce que vous faites, vous pouvez vous assurer que les données sont accessibles ou manipulées de la manière la plus efficace possible. Cependant, sachez que, plus souvent que que non, il existe d'autres domaines de votre code où vous pouvez faire des améliorations de performance nécessaires sans resoirting aux pointeurs. Essayez d'utiliser un profileur de code pour rechercher des goulots d'étranglement dans votre code - on vient avec Visual Studio 2008. »

Et si vous utilisez le pointeur de votre code exigera levier plus élevé de confiance pour exécuter et si la l'utilisateur ne concède que votre code ne fonctionnera pas

et l'envelopper avec une dernière citation:.

« Nous avons fortement des conseils contre l'utilisation de pointeurs inutilement becau se il non seulement être plus difficile à écrire et déboguer, mais également échouer la mémoire contrôles de type sécurité imposées par le CLR. »

+0

Pouvez-vous poster le lien pour votre information? – Alerty

+1

C'est un livre que j'ai acheté: http://www.wrox.com/WileyCDA/WroxTitle/Professional-C-2008.productCd-0470191376.html –

+0

Okay! Merci: D – Alerty

8

Je peux vous donner une situation où il était intéressant d'utiliser :

Je dois générer un bitmap pixel par pixel. Drawing.Bitmap.SetPixel() est beaucoup trop lent. Donc, je construis mon propre Array géré des données bitmap, et utilise unsafe pour obtenir le IntPtr pour Bitmap.Bitmap(Int32, Int32, Int32, PixelFormat, IntPtr).

+1

Oui, les bitmaps n'ont toujours pas une API 'gérée' rapide. –

1

Garbage Collection est inefficace avec des objets de longue durée. Le garbage collector de .Net fonctionne mieux quand la plupart des objets sont libérés assez rapidement, et certains objets "vivent pour toujours.«Le problème est que les objets qui vivent plus longtemps ne sont libérés que pendant les collectes complètes des déchets, ce qui entraîne une pénalité importante pour les performances.En résumé, les objets à vie longue passent rapidement à la génération 2.

(Pour plus d'informations, vous pouvez: lire sur le garbage collector générique de .Net: http://msdn.microsoft.com/en-us/library/ms973837.aspx)

Dans les situations où les objets, ou l'utilisation de la mémoire en général, vont être de longue durée, la gestion manuelle de la mémoire donnera de meilleures performances car elle peut être libérée dans le système sans Mise en œuvre d'une sorte de système de gestion de la mémoire basé sur un seul grand système de gestion de la mémoire. Un tableau d'octets, des structures et beaucoup d'arithmétique de pointeur pourraient théoriquement augmenter les performances dans des situations où les données seront stockées dans la mémoire RAM pendant une longue période.

Malheureusement, je ne suis pas au courant d'un bon moyen de faire de la gestion manuelle de la mémoire dans .Net pour les objets qui vont durer longtemps. Cela signifie essentiellement que les applications qui ont des données de longue durée dans la mémoire RAM ne répondent plus régulièrement lorsqu'elles exécutent une récupération complète de la mémoire.