2010-09-22 12 views
5

Jestem zainteresowany najkrótszym, najmodniejszym fragmentem kodu C#, który w niezawodny sposób wygeneruje błąd segfault - najlepiej bez bezpośredniego wywoływania jakiegokolwiek niezarządzanego kodu.Co to jest kanoniczna metoda generowania błędu segmentacji w języku C#?

+1

Nie prawdopodobne. Segfault w kodzie zarządzanym oznaczałby błąd w JIT/środowisku wykonawczym, aw niektórych przypadkach także lukę. Jeśli to możliwe, zostanie to wkrótce naprawione. – viraptor

+0

Pełna odpowiedź na to pytanie powinna wynosić tylko kilkanaście linii. –

+0

@viraptor: Nie, środowisko wykonawcze może obsłużyć błąd segmentacji (w systemie Windows jest to termin "naruszenie zasad dostępu") i wygenerować wyjątek NullPointerException, ale to nie to samo, co niepowodzenie segmentacji. Wszystko czego potrzebujesz to niezweryfikowalny kod (w języku C#, to znaczy kompilowanie '/ unsafe') –

Odpowiedz

7

To, o co panu chodzi, jest nieco niejasne, ale sądzę, że jest to tak dobre jak jakakolwiek dotychczasowa odpowiedź, i jest tak minimalne, jak tylko można.

System.Runtime.InteropServices.Marshal.ReadInt32(IntPtr.Zero);

+0

Tak, dziękuję. Tego właśnie szukałem. – Tom

0

skompilować z csc z opcją /unsafe:

class Program 
{ 
    static void Main(string[] args) 
    { 
     unsafe 
     { 
      int *p = null; 
      *p = 5; 
     } 
    } 
} 
+2

To faktycznie rzuca wyjątek NullReferenceException, który jest dość łatwy do uzyskania ze zwykłego starego .NET. Zakładam, że OP jest po coś bardziej przypomina wyjątek AccessViolationException. –

+0

Pod pokrywami naruszenie dostępu (natywny kod wyjątku 0xC0000005) wynika z dereferencji wskaźnika pustego, która jest następnie przechwytywana przez CLR i tłumaczona na wystąpienie "System.NullReferenceException". –

0

Jak zauważył w komentarzach powyżej, nie ma czegoś takiego jak segfault w systemie Windows, a nie mówi nic o mono na Linux. Zakładam, że w rzeczywistości chodziło o naruszenie dostępu.

Oto sposób, aby uzyskać jedno:

unsafe { 
    int* a = (int*) -4; 
    *a = 0; 
} 

(musi być skompilowany z opcją /unsafe).

Moja pierwsza próba stosowany 0 jak adres, ale okazało się to rzucać zwykły stary Wyjątek NullReferenceException, który można uzyskać bez niebezpiecznego kodu. Ale adres ujemny dostaje wyjątek AccessViolationException na moim pudełku Vista x64.

+0

Co ciekawe, powoduje to 'NullReferenceException' na Mono 1.9.1 działa pod Linuksem, więc myślę, że jest to zależne od architektury (lub Mono robi to źle!). –

+0

Dzięki. Jeśli chodzi o terminologię, cieszę się, że "naruszenie zasad dostępu" nazywa się segfault - zawsze tak było. – Tom

0

odpowiedź Michaela nie działa dla mnie, chyba że sprawa zostanie złapany teraz. Marshal.ReadInt32() po prostu daje mi "SystemError: Próba odczytu lub zapisu chronionej pamięci." z .NET 4.5 w Windows dla różnych przekazanych wartości. Użyłem jednak następujących rzeczy, które mogą być dla mnie zarówno w Windows, jak i pod mono 4.0.4.1:

using System.Runtime.InteropServices; 

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 
    public delegate void UNMANAGED_CALLBACK(); 

    public void Crash() 
    { 
     var crash = (UNMANAGED_CALLBACK)Marshal.GetDelegateForFunctionPointer((IntPtr) 123, typeof(UNMANAGED_CALLBACK)); 
     crash(); 
    }