2011-09-28 2 views
-2

예상되는 분할 오류로부터 안전하게 복구하려고합니다. 내 canAlloc() 함수를 사용하여 검사를 피하려고합니다. canAllow가 false를 반환하면 A0 (Ackermann이 표시되지 않는 경우)는 main 메소드에서 catch 할 수있는 예외를 throw해야합니다. checkTable과 saveInTable은 모두 map<int hash, int value>을 사용하여 A0의 반환 값을 저장하는 함수입니다. 코멘트에서 C++에서 C 동적 메모리 함수를 사용하여 분할 오류 방지

bool canAlloc(){ 
    bool reBool = false; 
    int * memch = (int*)calloc (10000, sizeof(int)); 
    reBool = (memch != NULL); 
    free(memch); 
    return reBool; 
    } 


    int A0(int m, int n){ 
if(!canAlloc()) throw; 

int reInt = checkReturnTable(m,n); 
if(reInt == -1){   
    if(m == 0){ 
     return n + 1; 
    } else if(m > 0){ 
      if(n == 0){ 
       reInt = A0(m-1,1); 
      } else if(n > 0){ 
       reInt = A0(m-1, A0(m,n-1)); 
      } 
    } 
    saveInReturnTable(m,n,reInt); 
    return reInt; 
} else return reInt; 
} 

:

주에서 나는 예외 try{} catch(...){}를 잡기 위해 try-catch 블록을 가지고있다. 내가 알기론 세 가지 기간은 던져진 예외를 잡아야한다. 그리고 내가 알고 있듯이 throw 키워드는 지정자없이 예외를 던지지만 여전히 3 개의 점으로 잡힐 수 있습니다.

+3

"'throw'을?" 다시 무슨 언어입니까? – cnicutar

+0

질문을 이해할 수 없습니다. 그리고 거기에 수표는별로 알려주지 않습니다. 한 시점에서 일부 메모리를 할당 할 수 있다고해서 다른 시점에 메모리를 할당 할 수있는 것은 아닙니다. – johannes

+0

'던짐'무엇? :) –

답변

4

세그먼트 화 오류는 C++ 예외가 아닙니다. OS가 프로그램에 SIGSEGV 신호를 보내는 프로그램 오류를 나타냅니다. catch SIGSEGV 신호를 직접 수신 할 수 없습니다. 당신은 시그널 핸들러를 셋업해야만 할 것입니다. 그리고 그 시점에서 까다로워집니다. 왜냐하면 당신이 시그널 핸들러 내에서 예외를 던질 수 있는지 분명하지 않기 때문입니다.

예외가 지정되지 않은 throw은 현재 예외를 다시 발생시킵니다. catch 블록 내부에서만 의미가 있습니다.

가상 메모리가 부족하여 시스템에서 더 이상 스택을 확장 할 수 없을 때 SIGSEGV가 표시됩니다. 즉, 인수 나 로컬 변수 또는 주소 등을 넣을 공간이 없기 때문에 함수 호출 중 하나가 실패했다는 것을 의미합니다. 복구 할 수있는 깨끗한 방법이 없으므로 시스템이 세그먼트 오류를 ​​생성합니다.

calloc()이 메모리를 할당 할 수 없기 때문에 오류가 발생한 경우 세그멘테이션 오류가 발생하지 않습니다. 당신은 반환 값이 0이 될 것입니다. 그리고 'out of memory'예외를 깨끗하고 동 기적으로 발생시킬 수 있습니다. 그러나 그것은 당신의 문제가 아닙니다.

+0

SIGSEGV가 발생 된 후에는 프로그램을 종료하기위한 옵션 이외에 다른 옵션이 거의 없습니다. 이것에 대한 신호 처리기를 작성할 수는 있지만 메시지 나 다른 것을 인쇄 할 수있는 것과는 다릅니다. – ASLilly

+2

오른쪽 - SIGSEGV 신호를 얻기 위해 방해가되는 프로그램을 작성하지 마십시오. 그것은 무언가가 끔찍하게 잘못되었음을 나타냅니다. 십대들이 조금 잘못한 것은 아닙니다. 치명적인 오류. 'calloc()'이 실패하면, 당신은 SIGSEGV를 얻지 못한다; 당신은 0의 반환을 얻는다. 그 시점에서 '메모리 부족'예외를 깨끗하게 제기 할 수 있습니다. –

+0

+1 : 신호/예외 혼동을 명확히하려는 경우. – AAT

1

일단 오류가 발생하면 프로그램이 더 이상 잘 정의 된 상태가 아니며 잘 정의 된 상태로 롤백 할 메커니즘이 없으므로 을 세그먼트 화 오류에서 복구 할 수 없습니다.

세그먼트 나누기 오류는 항상 한 가지 방법 또는 다른 프로그래밍 오류입니다. 사용자는이를 방지해야합니다. 당신은 적절한 관리 컨테이너 (같은 unique_ptr 또는 shared_ptr) 내부에 동적 할당을 감싸는 것이기 때문에

T * p; 
try { p = new T; } 
catch(const std::bad_alloc & e) { /* ... */ } 

일반적으로 상당히 그 매뉴얼이 될 필요는하지만,이 없다 : C++, 당신은 단순히 동적 할당에서 오는 예외를 잡을 수 있습니다 , 당신은 오류를 처리하고 의미있게 계속할 수있는 위치에있는 프로그램 흐름의 지점에서 예외를 잡아야한다.

(예외 덕분에 호출 측에서 기능을 던질 가능성이있는 결과를 확인하지 않아도됩니다. 즉 예외 사용의 요점입니다.)


만약 당신이 단지 원시 메모리를 할당 할 어떤 이유로, 어떤 객체를 구성하지 않고, 당신은 두 가지 방법으로 그것을 할 수

:

// Method #1, the C++ way: 
void * addr = ::operator new(n); // will throw std::bad_alloc on error 

// Method #2, the manual way: 
void * addr = std::malloc(n); 
if (!addr) throw std::bad_alloc(); // throw exception manually, handled elsewhere 
+0

그래,이게 내가 위의 코드에 어떻게 적용 할 수 있을까? – ASLilly

+0

전체 함수 호출을 try 블록으로 래핑하면되지만 실제로는 오류 조건에 응답 할 수있는 프로그램 흐름의 한 지점에서만 호출됩니다. 오류를 전파하려는 경우 예외를 포착 할 필요가 없습니다. –