2010-02-12 4 views
9

obj = null 또는 obj.member = null과 같은 오류 조건에 대한 응답으로 여러 가지 C# 응용 프로그램 충돌이 발생했습니다. 3rdPartyApp의 인터페이스에서 많은 시간, obj. 그리고 3rdPartyApp와 MyCsApp가 모두 충돌했습니다.모든 예외를 삼키고 응용 프로그램이 손상되는 것을 어떻게 방지합니까?

모든 가능한 영역에서 예외 처리를 추가하여 이러한 상황에서 응용 프로그램이 생존 할 수있는 방법은 무엇입니까? 모든 장소에 try-catch를 추가하고 상황을 복구하는 것은 어려운 일입니다.

현실적이고 신뢰할 수 있으며 방탄하는 방식으로 어떻게이 작업을 수행 할 수 있습니까?

[업데이트 : 산업 자동화 제어]

구조 :

GUI (asp.net, C++) - RuntimeApp (C++) - MyCsApp (CS) - 3rdPartyApp (고사)

일반 절차 :

  1. HostApp는 - (이더넷 Cabele를 통해 연결) - MyCsApp에게
  2. 운영자 - GUI -의 Ru를 ntimeApp - MyCsApp

이상 조건 :

  1. 일부 비표준 작업 절차;
  2. 일부 하드웨어 문제가 발생했습니다.

더 나은 모든 abnormall 조건을 처리하는 것 등. 그리고 가장 중요한 것은, 나는 상황에서 어떻게 회복해야하는지 생각해야합니다. 당신은 확실히 시도 캐치를 추가해서는 안

+16

대신 버그를 수정하는 것은 어떻습니까? – Aaronaught

+0

@Aaronaught, 우리는 이미 일부 장소를 현재 보호하고 있습니다. 즉, 비정상적인 작업에서 cursh가 발생한 후에 만 ​​고칠 수 있음을 의미합니다. MyCsApp는 3rdPartyApp을 기반으로하는 다중 스레드 응용 프로그램입니다. 여러 종류의 로그 (HostApp 로그, runtimeApp 로그, MyCsApp 로그 및 3rdPartyApp 로그)를 읽어야하며 문제를 복제하기 위해 최선을 다해야합니다. 그런 다음 해결할 수 있습니다. –

+8

두 단어. 하지 마. 젠장, 그게 셋이야 ... 지금은 왜 그런지 말할 수있을거야. 필요할 때 앱이 정상적으로 종료되지 않게 할 수 있습니다. 아래의 다른 사람들이 언급 한 전역 및 스레드 수준의 예외 처리기를 사용하는 경우 도달했을 때해야 할 일에 대한 계획을 세우십시오. . . 버그를 수정하는 데 콜 스택을 포함하여 오류를 로깅하는 것이 좋습니다. 대부분의 경우에 앱을 계속 유지하는 것은 좋은 생각이 아닐 수도 있지만 ... 다시 한 번 ... 코드와 환경을 알고 있는지 확인하십시오. –

답변

2

우선 질병을 치료하고, 왜 코드가 충돌하는지 확인하십시오. 코드가 obj = null 또는 이와 유사하여 충돌합니다. 예외 처리를 사용하고 모든 예외 사항을 삼키는 것은 문제를 마스킹하는 것입니다. 그것은 무엇을 위해 사용되지 않습니다!충돌을 유발하는 코드 - 냄새가 많이 나는 것처럼 들립니다. 응용 프로그램을 손상으로부터 보호하는 것은 문제를 해결하고 상황을 악화시키는 올바른 방법이 아닙니다. ...

좋아, John Saunders와 pm100 님의 제안은 ... 근본 원인을 확인하는 방법으로 처리하고, '마법의 은제'로 취급하지 말고, 하루가 끝날 때 제 3 자 응용 프로그램과 상호 작용하는 코드

예를 들어 ... 철저하게 디버깅 할 필요가

 
object foo = null; 
bar baz; 

// .... 
// foo is now set by thirdparty app 

if (foo != null && foo is bar) baz = (bar)foo as bar; 

if (baz != null){ 

    // Continue on, baz is a legitimate instance of type 'bar' 

}else{ 

    // Handle it gracefully or throw a *user defined exception* 

} 

사용 '으로'를 확인하는 방법을 통지하는 경우 '갑' '바'인스턴스의 적당한 유형이다 - 지금과 비교, 그것은이 도움이

 
object foo = null; 
bar baz; 

// foo is now set by thirdparty app - ARE YOU REALLY SURE ITS NON-NULL? 
// IS IT REALLY OF TYPE 'BAR'? 

baz = foo; // CRASH! BANG! WALLOP! KERRUNCH! 

희망, 안부, 톰 ... 전형적인 코드 냄새입니다.

+0

@ tommieb75 & Aaronaught. 귀하의 회신을 회사 신청 솔루션으로 받아 드리고 싶습니다. ** 근본 원인을 찾고 수정하십시오 **. @모든. 나는 당신의 답장을 토대로 더 많은 연구와 연습을하고 싶습니다. 가능한 경우 ** 서브 모듈 수준 ** 충돌 핸들을 솔루션에 추가하려고합니다. 감사합니다. –

4

사방

당신은 모든 예외의 최고 수준의 캐치가 필요합니다. 이것이 GUI 응용 프로그램 인 경우 '지원을 요청하십시오'라는 버튼이있는 멋진 대화 상자 만 표시됩니다 (스택 추적 스냅 샷을 화면이나 파일에 쓸 수 있음)

운이 좋으면 응용 프로그램에서 다음을 수행 할 수 있습니다. 당신이

 AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); 
     Forms.Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); 

을 할 수

메모를하지만 나던은 crshing 중지 (당신이 정말 심하게 붙어있는 경우 알 방법이 없기 때문에 운이) 계속, 그것은 단지 당신이 실패를 캡처 할 수 있습니다

19

당신은 가 아닙니다. 모든 곳의 모든 예외를 catch하고 싶습니다.

응용 프로그램의 하위 계층에서 예외가 누출되어 응용 프로그램을 종료하거나 손상시킬 수있는 위치까지 예외를 방지하려고합니다.

그러나 손상 방지는 단순히 예외를 포착하는 것 이상을 요구합니다.예외가 발생할 수있는 모든 지점에서 응용 프로그램이 항상 방해를받지 않도록해야합니다. 이는 복잡한 작업을 정리해야한다는 의미 일 수 있습니다. 예를 들어 :

ComplexBuilder cb = new ComplexBuilder(); 
try 
{ 
    cb.AddOperation(...); // Once building starts, 
    cb.AddOperation(...); // it's not safe to use cb 
    cb.AddOperation(...); 
} 
catch (SpecificException ex) 
{ 
    cb.Cleanup();   // until it's cleaned up 
} 

// Now safe to access cb, whether or not an exception was thrown 

는 최근 비슷한 태도와 응용 프로그램에 달렸다. "중요"하다고 여겨지는이 응용 프로그램이있었습니다. 그 "중요한"일이 일어 났을 때, 일어날 예정 이었지만 "중요하지 않은"것으로 여겨지는 다른 것들이있었습니다. 그 아이디어는 "중요하지 않은"부분에 예외가있는 경우 "중요한"부분을 계속해야한다는 것이 었습니다.

어떤 일이 발생했는지는 어떤 이유로 리소스를 읽지 못했습니다. 이것은 문자열 리소스 대신 null을 반환했습니다. 이로 인해 String.Format 호출에서 ArgumentNullException이 발생했습니다. 이로 인해 방금 계속 된 코드에 의해 예외가 잡히게되었습니다.

그러나 첫 번째 예외와 마지막 것 사이에 개체가 할당되고 개체에 대한 참조가 설정되어야했습니다. 그러나 예외 때문에 참조 설정이 절대로 발생하지 않았습니다. 결과는 NullReferenceException, 스택 레벨 4 개, 실제 문제가 발생한 곳의 두 개의 .csproj 파일을 보았습니다.

그래서 프로그램을 계속 진행할 수 있도록 예외를 잡는 것에 대해 이야기 할 때는 프로그램의 제어 흐름이 이러한 모든 예외를 포착하여 크게 변경된다는 점을 명심해야합니다. 사실, 프로그램을 계속 실행하는 것이 안전한지 여부를 더 이상 결정할 수 없을 정도로 많이 변경 될 수 있습니다.

+2

딩, 딩, 딩. 우승자가 있습니다. – mmcdole

0

이러한 예외를 피하기위한 한 가지 방법은 the null object pattern을 사용하는 것입니다. 그래서 그 대신 당신이 Account account = Account.SpecialNullAccount;을 할 것이다 당신의 계정 클래스에서 정적 Account 개체로 SpecialNullAccount를 정의 할 Account account = null; 갖는

. 이제 account.Name을 로깅 코드와 같은 중요한 코드에서 사용하려고 시도하면 예외가 발생하지 않고 정적 null 객체 인스턴스에 정의 된 "NO NAME"과 같은 값을 얻습니다.

물론 이러한 개체가 .PayInvoice() 또는 objectContext.SaveChanges()와 같은 중요한 경우 예외를 throw하므로 중요한 작업을 수행하는 것이 중요합니다.

+1

@Hightechrider : 예, null 객체 패턴은 예외를 방지하지만 더 이상 프로그램을 수정하지는 않습니다. 예외를 가지고 응용 프로그램을 안전하게 유지 한 다음 문제를 해결하는 것이 좋습니다. –

+0

@ John Saunders null 값 패턴이 코드를 향상시키지 않는다는 것에 동의하지 마십시오. null 값 패턴은 실제로 필요하지 않은 무의미한 예외를 방지합니다 (예 : log (account.Name)은 사용자가 로그인하지 않았으므로 Exception을 원하지 않음). 그리고 잊어 버린 것 변수를 초기화하고 의도적으로 아직 설정되지 않은 값을 갖는 경우 : PayInvoice()가 실패하면 사용자가 로그인하지 않았기 때문에 계정 값이 설정되지 않았기 때문인지 또는 사용자가 로그인하지 않았기 때문에 즉시 볼 수 있습니다. –

+0

OO의 Null 객체 패턴이 매우 있습니다. 데이터베이스의 'NULL'값과 비슷하지만 몇 가지 문제가 해결되지만 새로운 문제가 발생합니다. "fail fast"를 방지하여 프로그램이 오랫동안 잘못 실행되어 나중에 신비하게 실패 할 수 있습니다. 이 시나리오에서 정확성을 보장하는 데 도움이되는 것은 SpeC#에서 구현 된 것과 같이 null이 허용되지 않는 유형이지만 코드를 안정적으로 사용하고 어디서나 충돌하지 않는 것과 같은 확장을 도입해야 할 때입니다. – Aaronaught

0

AppDomain.UnHandledException 및/또는 AppDomain.ThreadException은 처리되지 않은 예외를 catch하기 위해 구독 할 수있는 이벤트입니다. 나는 이것을 사용하여 중단 된 곳에서 실행을 계속할 수 있다고 생각하지 않습니다. (어쨌든 이것은 좋은 생각이 아닙니다.) 그들은 오류 메시지를 삼키거나 기록하는 데 사용할 수 있습니다.

그러나 이것이 좋은 생각인지는 여러분에게 달려 있습니다!

+1

이 조언에 대한 한 가지 경고는 나쁜/복구 할 수없는 상태로 인해 예외가 발생하면 실제로 앱이 오작동을 일으켜 사용자를 완전히 좌절시킬 수 있다는 것입니다. 확실히 충돌하는 앱을 다루는 것은 실망 스럽지만 지나치게 잘못한 앱을 다루는 것은 더욱 좌절스러운 일입니다. –

0

는 윈폼 응용 프로그램과 같이 Main 메서드에 다음과 같은 이벤트에 대한 이벤트 처리기를 추가하는 경우이

Application.ThreadException += Application_ThreadException; 
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; 
그런 다음, 메시지 박스 또는 다른 통지를 보여 예외에 등을 100g을하고 충돌없이 작업을 계속할 수 있습니다

앱.

+0

이 조언에 대한 한 가지 경고는 나쁜/복구 할 수없는 상태에 있기 때문에 예외가 발생하면 실제로 앱이 오작동하고 사용자를 완전히 좌절시킬 수 있다는 것입니다. 확실히 충돌하는 앱을 다루는 것은 실망 스럽지만 지나치게 잘못한 앱을 다루는 것은 더욱 좌절스러운 일입니다. –

+0

제이슨과 동의하십시오. 나는 개별적인 나쁜 데이터로 인해 오류가 있고 일반적으로 오류가없는 LOB 앱을 설명했다. 그래서 예외를 잡은 후에 행복하게 계속할 수 있습니다. 함께 작업하는 또 다른 데이터 세트에는 전혀 문제가 없을 수 있습니다. – softveda

+0

나는 "행복하게"계속 할 수 있다고 말하지 않겠다. * 최소한 이러한 오류는 철저히 기록되고, 조사되고, 추적되고, 정상적이고 조직적인 방식으로 해결되어야합니다. 간단히 파일을 건너 뛰거나 암호 해독 된 디버그 메시지를 출력하면 * 응용 프로그램 *이 계속 실행될 수 있지만 비즈니스 * 속도는 매우 빠릅니다. – Aaronaught

7

많은 개발자가 얻지 못하는 것입니다. 예외 캐치 올 (catch-all)이 발생하면 응용 프로그램이 이미 충돌했습니다. 무언가 예기치 않은이 발생했습니다. 즉, 코드가 예상하지 못했을 때 상황이 불확실한 상태에 놓일 가능성이 매우 높습니다 (예 : 예외가 발생한 지점에서 완료된 불쾌한 함수의 양을 정확히 알 수 없습니다. 생성 된 데이터가 얼마나 많은지, 하드웨어에서 설정 한 비트 등을 알지 못합니다. 계속하는 것이 안전합니까? 사용자의 데이터를 저장해야합니까? 누가 알아!

높은 수준의 캐치를 모두 제공하면 은 앱이 충돌하지 않도록을 막지 않았습니다. 이 시점에서의 충돌에 대해 무엇을 할 것인지 결정하는 것은 입니다. 당신은 표준과는 다른 메시지를 넣을 수 있습니다 :

이 응용 프로그램에서 잘못된 연산

을 수행 ...하지만 그 어떤 더 나은 말을하려고 사용자 정의 메시지는 무엇인가?

우리는 계획되지 않은 유지 보수를 위해 경고없이 종료하지만 그것이 ...이 우수한 소프트웨어

에 으로 결함을 할 아무것도 없다고 안심하고

?

관련 문제