2010-07-22 7 views

Odpowiedz

26

Nie powinieneś. Naruszenie dostępu jest poważnym problemem: jest to nieoczekiwana próba zapisu na (lub odczytanie) nieprawidłowego adresu pamięci. Jak już wyjaśnił John, niezarządzana biblioteka DLL mogła już uszkodzić pamięć procesową, zanim zostało naruszone prawo dostępu. Może to mieć nieprzewidziane skutki w dowolnej części bieżącego procesu.

Najbezpieczniejszą rzeczą do zrobienia jest poinformowanie użytkownika, a następnie natychmiastowe wyjście.

Kilka dodatkowych informacji: Naruszenie zasad dostępu to wyjątek systemu operacyjnego (wyjątek o strukturze strukturalnej SEH lub z wyjątkiem obsługi). Jest to inny rodzaj wyjątku niż zarządzane wyjątki CLR z System.Exception. Rzadko widzi się wyjątki SEH w czysto zarządzanym kodzie, ale jeśli wystąpi, np. w niezarządzanym kodzie CLR dostarczy go do kodu zarządzanego, gdzie można go również złapać: .

Jednak złapanie wyjątków SEH w większości przypadków nie jest dobrym pomysłem. Dalsze szczegóły są opisane w artykule w czasopiśmie Handling Corrupted State Exceptions MSDN gdzie Poniższy tekst to zaczerpnięte z:

CLR zawsze dostarczane wyjątki SEH do kodu zarządzanego przy użyciu tych samych mechanizmów jak wyjątki podniesione przez sam program. Nie stanowi to problemu, o ile kod nie próbuje poradzić sobie z wyjątkowymi warunkami, których nie można racjonalnie obsłużyć. Większość programów nie może bezpiecznie kontynuować wykonywania po naruszeniu dostępu. Niestety, model obsługi wyjątków CLR zawsze zachęcał użytkowników do łapania tych poważnych błędów, umożliwiając programom wychwycenie dowolnego wyjątku u góry hierarchii System.Exception. Ale rzadko jest to słuszne.

To była prawda aż .NET 3.5. W .NET 4 zachowanie zostało zmienione. Jeśli nadal chcesz być w stanie wychwycić tego rodzaju wyjątki, musisz dodać legacyCorruptedState­­ExceptionsPolicy=true do pliku app.config. Dalsze szczegóły w wyżej wymienionym artykule.

+4

Aby wyjaśnić: powodem, dla którego chcesz wyjść z ASAP, jest to, że nie wiesz, co niezarządzana biblioteka DLL zastąpiła zanim trafi ona na naruszenie dostępu. Możliwe, że pisał śmieci w wystarczającej ilości miejsc, których program nie może bezpiecznie kontynuować. –

+0

@John Saunders: Dzięki za wyjaśnienia. Zaktualizowałem swoją odpowiedź. –

+4

Mogę wymyślić jeden bardzo dobry powód, aby to złapać: Jeśli masz proces bezobsługowy i nie masz go, zamiast wyjść, proces zawiesza się w oknie dialogowym Wykluczenie dostępu, które nie pokazuje nikogo w szczególności. Catching to pozwala wyjść bez tego okna. – jpwkeeper

0

Możesz zawinąć wywołanie do niezarządzanej biblioteki DLL blokiem try-catch. AccessViolationExceptions można złapać normalnie. Wykonywanie Poniższy kod przedstawia oba komunikaty:

try 
{ 
    throw new AccessViolationException(); 
} 
catch (Exception e) 
{ 
    MessageBox.Show(e.Message + e.StackTrace, e.Message, MessageBoxButtons.OK, MessageBoxIcons.Error); 
} 
MessageBox.Show("Still running.."); 

Edit: .NET 4 wprowadziła change in behavior, to nie jest już możliwe, aby złapać uszkodzone wyjątki Państwie, chyba że wyraźnie "ask" runtime zrobić.

+0

Pytanie brzmi, czy to dobry pomysł, aby to zrobić? Może być rozsądne, aby wyświetlić miły i przyjazny komunikat dla użytkownika i napisać dziennik. Ale praca dalej niż to nie jest dobry pomysł ... – rioki

+0

Prawdopodobnie nie, przynajmniej nie, jeśli nie jesteś absolutnie przekonany, że nic złego się nie stało. – andyp

+2

To nie działa. Próbowałem przechwycić wyjątki Exception i AccessViolationException, ale ignoruje mój blok catch. Zakładam, że potrzebuję jakiejś flagi app.config. –

1

Przede wszystkim w pełni z 0xA3. Ale jeśli nie ma wyjścia, możesz zawinąć brudną niezarządzaną bibliotekę DLL w swój własny proces i przesłać dane przez IPC (TCP/IP, namedpipes, itp.). Złap wszystkie wyjątki i poinformuj proces hosta. Więc twój proces hosta jest w większości ratowany przed uszkodzeniem pamięci.

6

Tak.

W Twojej aplikacji.confg, plop następujący kod w tagu <configuration>:

<runtime> 
    <legacyCorruptedStateExceptionsPolicy enabled="true"/> 
</runtime> 

Teraz powinieneś być w stanie złapać uszkodzone wyjątki państwowych (CSE) jak każda inna.

Uwaga: Jeśli masz już tag wykonania po prostu dodać do niego <legacyCorruptedStateExceptionsPolicy enabled="true"/>

Powyższe prace dla .Net 4.5

+1

th za to. Przeczytałem kilka odpowiedzi na ten problem. wszyscy mówią "dodaj" 'do' app.config' ", ale nikt nie powiedział, że nie powinien być w domyślnej sekcji' '. Dziękuję za podpowiedź w sekcji "" – user1234

2

Jak inni wskazał, że nie powinno „obsłużyć” ten warunek, ale w trakcie rozwoju przydatne jest złapanie tego w celu rozwiązania problemu.

Można oznaczyć zarządzanej metody z atrybutem System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions:

[HandleProcessCorruptedStateExceptions] 
public void MyMethod() 
{ 
    try 
    { 
     NaughtyCall(); 
    } 
    catch (AccessViolationException e) 
    { 
     // You should really terminate your application here 
    } 
}