2013-08-21 2 views
8

В основном, повреждение памяти вызвано перезаписью памяти, которую вы не должны перезаписывать. Мне интересно, возможно ли это с помощью небезопасного кода в C# (т. Е. Не путем вызова внешнего неуправляемого кода). Я вижу два возможных случая:Может ли небезопасный код на C# вызывать повреждение памяти?

  • Доступ к нулевому указателю -> захватывается CLR, бросает NullReferenceException
  • Доступа указателя на неправильное место случайной памяти -> захватывается CLR, бросает AccessViolationException

В обоих случаях кажется, что среда исполнения обнаруживает и предотвращает возникновение потенциального повреждения памяти. Таким образом, можно ли испортить память из C# с помощью небезопасного кода? И как следствие, безопасно ли улавливать AccessViolationExceptions из небезопасного кода?

+0

В C# это NullReferenceExcoption. И я сомневаюсь, что clr сделает одно и то же исключение для управляемых и неуправляемых нулевых различий. –

+0

Исправлено, спасибо. Да, это одно и то же исключение, вы легко можете попробовать это самостоятельно, т. Е. «Var ptr = (int *) 0; * ptr = 1; // throws NullReferenceException' – Asik

+0

Также обратите внимание, что в .net 4.0 по умолчанию ваш процесс будет прекращен, если есть индикация поврежденного состояния. http://msdn.microsoft.com/en-us/magazine/dd419661.aspx#Four –

ответ

9

Доступ указатель на неправильное место случайной памяти

Если это читать, это безопасно. Если это была запись, это небезопасно, если ячейка памяти оказалась действительной, но вы ее не владели. Вы будете писать по местам случайной памяти.

И как следствие, безопасно ли улавливать AccessViolationExceptions из небезопасного кода?

Нет, поскольку это исключение сообщает вам, что a) у вас есть ошибка, и b) что память может быть повреждена, что невозможно восстановить. Поймайте его и сорвите процесс как можно скорее.

+0

«Если это была запись, это небезопасно, если место памяти оказалось действительным, но вы его не владели». Если это вне границ вашего приложения, Windows убьет ваш процесс, AFAIK. – Renan

+0

@Renan, если вы не обработали исключение, да. – usr

+1

Я не совсем понимаю, почему память может быть повреждена, если выбрано AccessViolationException. Не означает ли тот факт, что CLR поймал попытку доступа к недопустимой памяти и, следовательно, не позволил ей произойти? – Asik

2

Память записи, которая вызвала AccessViolationException, не произошла, она ничего не делает.

Тем не менее: тот факт, что он пытался писать в неправильном месте, является очень сильным индикатором того, что раньше (поскольку ваш код был ошибкой) могут быть недопустимые операции записи, и эти записи могли указывать на местоположения, которые но не должны быть изменены.

6

Может ли небезопасный код на C# вызывать повреждение памяти?

Ответ да !, Рассмотрим следующий пример делает это

int a = 10; 
int* p = &a; 
*(p+54)= 444; 

CLR может или не ловушка это.

Не все считывания или записи с помощью плохих указателей приводят к нарушениям доступа, поэтому нарушение прав доступа обычно указывает на то, что несколько ошибок чтения или записи произошли с помощью плохих указателей, и эта память может быть повреждена.

Accessviolationexception Documentation От

10

Вы упускаете большую пулю:

  • доступа к памяти и не получение AccessViolationException.

Что очень часто, всегда есть много записываемой памяти вокруг в программе .NET. Включая запись элемента за конец массива, он редко бомбит. Защита памяти является зернистой на границах страницы памяти, 4096 байт в Windows. .NET GC сильно ударяет, сегменты кучи поколений являются хорошими большими кусками виртуальной машины. Ловить AVE очень неразумно.

Некоторые код, чтобы играть с:

class Program { 
    static unsafe void Main(string[] args) { 
     var arr = new byte[1]; 
     for (int fill = 0; fill < 2 * 1024 - 64; ++fill) { 
      byte[] dummy = new byte[1024]; 
     } 
     fixed (byte* p = &arr[0]) { 
      for (int ix = 1; ; ++ix) 
       p[ix] = 42; 
     } 
    } 
} 

проскакивает около 1,5 мегабайт.