Domanda

Quali sono le conseguenze (positivo / negativo) di utilizzare il non sicuri parola chiave nel C # per usare puntatori? Per esempio, che diventa di raccolta dei rifiuti, quali sono le prestazioni utili / perdite, quali sono i guadagni di prestazioni / perdite rispetto ad altre lingue gestione manuale della memoria, quali sono i pericoli, in quale situazione è davvero giustificabile a fare uso di questa lingua caratteristica, è più lungo per compilare ...?

È stato utile?

Soluzione

Come già detto da Conrad, ci sono alcune situazioni in cui l'accesso non sicuro alla memoria in C # è utile. Non ci sono come molti di loro, ma ci sono alcuni:

  • Manipolazione con Bitmap è quasi un tipico esempio in cui avete bisogno di qualche prestazioni aggiuntive che è possibile ottenere utilizzando unsafe.

  • Interoperabilità con API più anziani (come WinAPI o nativo C / C ++ DLL) è un'altra area dove unsafe può essere molto utile - ad esempio, si consiglia di chiamare una funzione che prende / restituisce un puntatore non gestito.

D'altra parte, si può scrivere la maggior parte delle cose utilizzando classe Marshall , che nasconde molte delle operazioni non sicure all'interno chiamate di metodo. Questo sarà un po 'più lento, ma è un'opzione se si vuole evitare di utilizzare unsafe (o se si sta utilizzando VB.NET che non ha unsafe)

conseguenze positive : Così, le principali conseguenze positive della esistenza di unsafe in C # è che si può scrivere del codice più facilmente (interoperabilità) e si può scrivere del codice in modo più efficiente (con la manipolazione di bitmap o forse alcuni calcoli numerici pesanti utilizzo di matrici - anche se, I' m non così sicuro circa il secondo).

Conseguenze negative : Certo, c'è qualche prezzo che si deve pagare per l'utilizzo di unsafe:

  • codice non verificabile : codice C # che è scritto utilizzando le funzionalità unsafe diventa non verificabile, che significa che il vostro codice potrebbe compromettere il runtime in alcun modo. Questo non è un grosso problema in un pieno di fiducia scenario (ad esempio senza restrizioni un'applicazione desktop) - semplicemente non si dispone di tutte le belle garanzie .NET CLR. Tuttavia, non è possibile eseguire l'applicazione in un ambiente ricercato ristretto come ad esempio l'hosting web pubblico, Silverlight o attendibilità parziale (ad esempio, un'applicazione in esecuzione dalla rete).

  • Garbage collector ha anche bisogno di fare attenzione quando si utilizza unsafe. GC è di solito permesso di riposizionare gli oggetti sul heap gestito (per mantenere la memoria deframmentato). Quando si prende un puntatore ad un oggetto, è necessario utilizzare la parola chiave fixed a dire il GC che non può spostare l'oggetto fino al completamento (che probabilmente potrebbe influire sulle prestazioni di raccolta dei rifiuti - ma, naturalmente, a seconda dello scenario esatto) .

La mia ipotesi che, se C # non ha dovuto interagire con il codice più vecchio, probabilmente sarebbe non supporta unsafe (progetti di ricerca e come Singularity che tentano di creare il sistema operativo più verificabile sulla base di lingue gestite sicuramente non permettere il codice usnsafe). Tuttavia, nel mondo reale, unsafe è utile in alcuni (rari) casi.

Altri suggerimenti

Posso darvi una situazione in cui valeva la pena utilizzando:

Devo generare un pixel per pixel bitmap. Drawing.Bitmap.SetPixel() è troppo lento. Così ho costruire la mia Array gestito dei dati bitmap, e utilizzare unsafe per ottenere il IntPtr per Bitmap.Bitmap( Int32, Int32, Int32, PixelFormat, IntPtr) .

Per citare professionale C # 2008:

  

"Le due ragioni principali per l'utilizzo   puntatori sono:

     
      
  1. compability indietro - Nonostante tutte le agevolazioni previste dal   NET-runtime è ancora possibile   chiamare funzioni API di Windows native, e   per alcune operazioni puo essere   unico modo per accompling il vostro compito.   Queste funzioni API sono generalmente   scritto in C e spesso richiedono   puntatori come parametri. Tuttavia, in   molti casi è possibile scrivere il   Dichiarazione DllImport in un modo che   evita l'uso di puntatori; per esempio,   utilizzando la classe System.IntPtr.
  2.   
  3. Performance - In quelle occasioni in cui la velocità è di fondamentale   importanza, puntatore può fornire una   rotta verso perfomance ottimizzato. Se tu   sa cosa si sta facendo, si può   assicurare che i dati si accede o   manipolato nel modo più efficiente.   Tuttavia, essere consapevoli del fatto che, il più delle volte   che no, ci sono altre aree di   codice in cui è possibile effettuare necessaria   improvemens prestazioni senza   resoirting ai puntatori. Provare a usare un   profiler del codice a cercare i colli di bottiglia   nel codice - si arriva con Visual   Studio 2008 ".
  4.   

E se si utilizza il codice di puntatore richiederà più alto la leva di fiducia da eseguire e se l'utente non concede che il codice non verrà eseguito.

E avvolgetelo con un ultima citazione:

  

"Siamo fortemente consiglio contro l'uso   puntatori inutilmente perché sarà   non solo essere più difficile di scrivere ed eseguire il debug,   ma sarà anche fallire la memoria   controlli tipo di sicurezza imposte dalla   CLR ".

Garbage Collection è inefficiente con oggetti longevi. garbage collector di Net funziona meglio quando la maggior parte degli oggetti vengono rilasciati piuttosto rapidamente, e alcuni oggetti "vivere per sempre". Il problema è che gli oggetti più lunghi vivente vengono rilasciati solo durante garbage collection completa, che incorre in una penalità di prestazioni significative. In sostanza, gli oggetti di lunga vita si muovono rapidamente in generazione 2.

(Per ulteriori informazioni, si potrebbe desiderare di leggere su generazionale garbage collector di .Net: http://msdn.microsoft.com/en-us/library/ms973837.aspx )

In situazioni in cui oggetti, o l'uso della memoria in generale, sta per essere longeva, gestione manuale della memoria produrrà migliori prestazioni, perché può essere rilasciato per il sistema senza richiedere una garbage collection completa.

L'implementazione qualche tipo di un sistema di gestione della memoria basata su un unico grande array di byte, le strutture, e un sacco di aritmetica dei puntatori, potrebbe teoricamente aumentare le prestazioni in situazioni in cui i dati saranno memorizzati in RAM per un lungo periodo di tempo.

Purtroppo, io non sono a conoscenza di un buon modo per farlo gestione manuale della memoria in .Net per gli oggetti che stanno per essere longeva. Ciò significa che le applicazioni che hanno i dati di lunga durata nella RAM saranno periodicamente non rispondere quando corrono una garbage collection completa di tutta la memoria.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top