Perché non usare un codice sicuro non gestito in C #


10

C'è un'opzione in C # per eseguire il codice non selezionato. In genere non è consigliabile farlo, poiché il codice gestito è molto più sicuro e risolve molti problemi.

Tuttavia mi chiedo, se sei sicuro che il tuo codice non causerà errori e sai come gestire la memoria, perché (se ti piace il codice veloce) seguire i consigli generali?

Mi chiedo questo da quando ho scritto un programma per una videocamera, che ha richiesto una manipolazione bitmap estremamente veloce. Ho creato alcuni algoritmi grafici veloci e funzionano in modo eccellente sulle bitmap usando un codice non gestito.

Ora mi chiedo in generale, se sei sicuro di non avere perdite di memoria o rischi di arresti anomali, perché non utilizzare il codice non gestito più spesso?

PS: il mio background: sono entrato in questo mondo della programmazione e lavoro da solo (lo faccio per alcuni anni) e quindi spero che questa domanda di progettazione del software non sia così strana. Non ho davvero altre persone là fuori come un insegnante per chiedere queste cose.


8
unsafesignifica "sapere cosa stai facendo e valutare i benefici rispetto ai rischi". Ho usato unsafeuna manciata di volte, ed è sempre stato per qualcosa di molto specifico in relazione alle prestazioni che poteva essere murato nel suo metodo. Non lo uso come tecnica di programmazione generale, poiché il più delle volte il vantaggio in termini di prestazioni non vale la perdita di sicurezza.
Robert Harvey,

14
Nel corso degli anni ho scritto un sacco di codice che a volte si arrestava in modo anomalo o presentava perdite di memoria, che ero abbastanza sicuro di non avere perdite di memoria o rischi di arresti anomali.
whatsisname

1
Ecco un buon unsafeesempio di caso d'uso: stackoverflow.com/q/11660127/102937
Robert Harvey,

3
Suppongo che il tuo codice bitmap abbia ancora dei bug, ma non li hai rilevati. E anche se non fosse così, aspetta di dover implementare alcuni nuovi requisiti nel codice esistente.
Doc Brown,

1
Perché anche quando sei sicuro che il tuo codice non causerà errori, causerà comunque errori.
user253751

Risposte:


27

Bene, è principalmente un caso del vecchio adagio

  • Non ottimizzare
  • (solo per esperti) Non ottimizzare ancora

Ma in realtà posso pensare a tre motivi principali per evitare codici non sicuri.

  1. Bug : la parte critica della tua domanda è "se sei sicuro che il tuo codice non causerà errori". Bene, come puoi essere assolutamente sicuro? Hai usato un prover con metodo formale che ha garantito il tuo codice corretto? Una cosa è certa nella programmazione, ed è che avrai dei bug. Quando decolli di sicurezza, permetti a un nuovo tipo di bug di insinuarsi. Quando lasci che il garbage collector si occupi della memoria per te, molti problemi scompaiono.

  2. Non sempre veloce come pensi : l'altro punto è: a seconda del problema, il guadagno potrebbe non essere così grande. Anche se non riesco a trovarli in questo momento, ricordo uno studio di Google che confronta la velocità di Java, Scala, Go e C ++. Una volta ottimizzato a terra, ovviamente C ++ era molto più veloce. Ma l'algoritmo programmato in modo "idiomatico" non era molto più veloce. Idiomatico nel senso che stavano usando la struttura standard e gli idiomi (contenitore stl, nessun anello non srotolato, ecc.). Microsoft ha fatto un esperimento simile con C # e C ++. Raymond Chen, uno dei migliori ingegneri Microsoft, ha dovuto scrivere la sua implementazione di std :: string per battere C #. (vedi: http://www.codinghorror.com/blog/2005/05/on-managed-code-performance-again.html) Per uno sforzo molto minore, hai ottenuto prestazioni abbastanza decenti nel codice gestito, quindi spesso non vale la pena.

  3. Riutilizzabilità : il codice non sicuro può essere utilizzato solo in un ambiente completamente affidabile. Ad esempio, in un server ASP.NET, di solito non è possibile utilizzare un codice non sicuro, poiché sarebbe piuttosto semplice introdurre una vulnerabilità tramite buffer overflow. Un altro esempio sarebbe clickonce. O se si accede alla propria applicazione da una condivisione di rete. Quindi, se prevedi di utilizzare il tuo codice in una varietà di scenari di distribuzione, il codice non sicuro è fuori gioco.

Quindi in sostanza: è malvisto perché può introdurre bug inutili, potrebbe non avere alcun guadagno e ridurre la riusabilità del codice.

Ma se il tuo scenario lo richiede davvero per le prestazioni (e disponi di dati per dimostrarlo), sei un programmatore esperto che sa come gestire la memoria e il tuo codice verrà utilizzato in un ambiente controllato, quindi assicurati.


4

In un certo senso, il codice non gestito è una forma di pagamento: acquisti più velocemente con lo sforzo di sviluppo extra. In effetti, il codice non gestito richiede più tempo per lo sviluppo, il debug e la manutenzione. Farlo esattamente nel modo giusto è una sfida per la maggior parte dei partecipanti. In un certo senso, questo è simile alla programmazione in assembly: certo, puoi scrivere più potenza dalla tua CPU se scrivi in ​​assembly * , ma "spendi" molto più sforzo lungo quella strada.

A volte, la differenza nei tempi di sviluppo è molto significativa: giorni anziché ore. Tuttavia, la differenza nella velocità di esecuzione non è altrettanto drammatica. Ecco perché lo sviluppo di codice non gestito è riservato a situazioni simili a quella che hai descritto nel tuo post - implementazioni localizzate, autonome, di algoritmi affamati di risorse, come l'elaborazione audio e video.

In sostanza, la risposta alla tua domanda è simile alla risposta del perché tutti non guidano la Ferrari: è un'auto molto migliore, giusto? (Un) per fortuna, non tutti possono permetterselo.


* I progressi degli ultimi decenni nella tecnologia di ottimizzazione dei compilatori hanno ridotto questo divario al punto da non essere più una scommessa sicura.


0

Perché essere "sicuri" della correttezza o di qualsiasi altro vincolo in senso matematico (cioè se si ha una prova) è un problema molto difficile per i linguaggi imperativi. I programmi hanno spesso un numero di stati così elevato che non è possibile verificarli anche controllando ogni stato possibile. E creare una dimostrazione costruttiva non è qualcosa che puoi automatizzare.

Quindi il motivo è che le assicurazioni che l'esecuzione gestita fornisce molto spesso sovrastimano il piccolo guadagno in termini di prestazioni che otterresti con un codice non sicuro. Naturalmente, questo dipende anche dal caso d'uso specifico.


1
Non penso che abbia nulla a che fare con la correttezza o la semplicità di ragionare ..
Jimmy Hoffa,

Nessuno sta parlando di una prova formale di correttezza.

1
Sono sicuro che il tuo post non rispetta il punto, ma non formulerò una prova formale. Allo stesso modo, posso essere sicuro che il mio programma sia corretto (ad es. Dopo test approfonditi, debug e uso prolungato del mondo reale senza che si siano verificati bug) senza provarlo una volta per tutte. Questa interpretazione è molto più vicina a ciò che la maggior parte della gente intende quando dicono "sicuro che è corretta". I metodi formali sono una preoccupazione molto di nicchia e completamente fuori considerazione per la maggior parte degli sviluppatori.

1
Non vedo questa domanda. La domanda, mentre la leggo, è perché il tratteggio di escape dal mondo gestito non è / non dovrebbe essere usato più spesso (il che implica che il default del codice gestito ha senso). In ogni caso, se vuoi rispondere a questa domanda (sottolineando la durezza di assicurare la correttezza), puoi farlo senza parlare dell'assicurazione formale e assoluta della correttezza. La tua risposta al momento ruota esclusivamente intorno a prove complete e valide di correttezza per le lingue imperative. Ma è eccessivo, e penso che le prove sul C # gestito siano ugualmente (o quasi) difficili.

1
@fish: posso vedere quello che stai dicendo. C'è una correlazione tra qualcosa che è difficile da dimostrare e qualcosa di cui è difficile ragionare. Se è difficile dimostrare che è corretto, allora è molto difficile essere abbastanza sicuri che sia giusto.
Michael Shaw,

0

In breve, nulla ti impedisce di fare tutto ciò che funziona e di gestire bit e bulloni del tuo programma in ambiente C ++. Dato che sei abbastanza sicuro di poter gestire correttamente tutti i cerchi e le perdite di memoria senza garbage collector, allora sei il benvenuto a farlo in C ++ :)

Al contrario, C # presenta vantaggi nel fornire un ambiente di sviluppo sicuro / gestito e fortemente tipizzato per l'esecuzione sicura in .NET framework.

Il possibile back-draw della programmazione di codice non gestito è il tempo di sviluppo più lungo, allocazione del tempo per test dettagliati. Naturalmente otterrai velocità di elaborazione e maggiore controllo sul funzionamento del tuo software.

Pertanto, l'opzione per lavorare con codice non gestito in .NET Framework a partire da 4.0 è un'opzione per casi limite quando sei sicuro che potrebbe portare a guadagni rispetto al non usarlo ...


Aha è interessante vedere che vengo dal mondo dei microcontrollori e di solito uno scrive c ++ decente, c'è poco spazio per gli errori e una buona progettazione del software è la cosa chiave da fare
user613326
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.