Per scopi didattici, sto scrivendo una serie di metodi che causano eccezioni di runtime in C# per capire quali sono tutte le eccezioni e cosa le causa. In questo momento, sto armeggiando con programmi che causano uno AccessViolationException
.Perché * (int *) 0 = 0 non causa una violazione di accesso?
Il modo più ovvio (per me) per fare questo è stato quello di scrivere in una posizione di memoria protetta, in questo modo:
System.Runtime.InteropServices.Marshal.WriteInt32(IntPtr.Zero, 0);
Proprio come avevo sperato, questo ha gettato un AccessViolationException
. Volevo farlo in modo più conciso, così ho deciso di scrivere un programma con codice non sicuro, e fare (quello che pensavo fosse) esattamente la stessa cosa assegnando 0
al puntatore zero.
unsafe
{
*(int*)0 = 0;
}
Per ragioni che mi sfuggono, questo getta un NullReferenceException
. Ne ho giocato un po 'e ho scoperto che l'utilizzo di *(int*)1
lancia anche un NullReferenceException
, ma se si utilizza un numero negativo, come *(int*)-1
, verrà generato un valore AccessViolationException
.
Cosa sta succedendo qui? Perché lo *(int*)0 = 0
causa uno NullReferenceException
e perché non causa uno AccessViolationException
?
'(int *) 0' è un puntatore nullo. Mi aspetterei pienamente un 'NullReferenceException'. Se vuoi una 'AccessViolationException', prova qualcosa come' (int *) 0x10' (o possibilmente '0xf0000000'). – cHao
possibile duplicato di [Perché l'accesso alla memoria è nello spazio degli indirizzi più basso (sebbene non nulla) segnalato come NullReferenceException da .NET?] (Http://stackoverflow.com/questions/7940492/why-is-memory-access-in -the-lowest-address-space-non-null-though-reported-as-n) –