오류 처리

EGL을 사용하여 오류 시 프로그램이 작동하는 방법을 결정할 수 있습니다.

오류 처리는 프로그램에서 발생할 수 있는 문제점의 유형을 예측하고 각각에 대한 코드 경로를 제공함을 의미합니다. 오류를 처리하지 않기로 결정하는 경우, 가장 사소한 것(이 주제의 뒤에 있는 "I/O 오류" 참조)을 제외한 모두가 프로그램 종료의 원인이 됩니다.

EGL에서의 오류 처리는 예외의 개념을 벗어나며 이는 레코드에 적용되는 스테레오타입입니다. EGL에는 다수의 사전 정의된 예외(EGL 언어 참조의 부록에서 "EGL 예외 레코드" 참조)가 있거나 사용자가 고유하게 정의할 수 있습니다. 각 예외 레코드는 최소한 다음 필드를 포함합니다.
messageID
예외에 대해 EGL 메시지를 포함하는 문자열입니다. 예를 들어, 초기화되지 않은 배열을 사용하려는 경우 EGL이 NullValueException 레코드의 messageID를 EGL0106E로 설정합니다.
메시지
문제점에 대한 간략한 설명을 포함하는 문자열입니다. 예를 들어, messageID가 EGL0106E인 메시지는 "널 참조를 사용했습니다."입니다.

예외 레코드는 적절한 경우 추가 필드를 포함할 수 있습니다. 예를 들어, IndexOutOfBoundsException에는 EGL이 처리할 수 없는 배열 색인의 값을 포함하는 indexValue에 대한 추가 필드가 있습니다.

시도 블록

EGL 시도 키워드는 예외를 발견하고 처리할 수 있는 코드의 블록을 도입합니다. 시도 블록 내에서 예외가 발생하는 경우 EGL은 예외 유형과 일치하는 시도 블록 내에서 onException 문을 찾습니다. 각 onException 문은 예외 변수에 대한 선언을 포함합니다. 이는 EGL에서 사용자가 선언하는 변수와 유사한 레코드 변수입니다. 선언은 다음과 같습니다.
onException(myEx NullValueException)
이는 EGL이 이 시도 블록 내부의 NullValueException을 처리하는 경우 사용자가 해당 예외 레코드의 필드에 액세스할 수 있음을 의미합니다. 예를 들어, 다음 예제와 같이 myEx.msgID에서 EGL 메시지 ID를 찾을 수 있습니다.
try
  intArray[10] = 0;  // 초기화되지 않을 수 있음
onException(myEx NullValueException)
  writeStdErr(myEx);
  myErrorHandler(myEx);
end

예를 들어, myErrorHandler() 기능은 배열 초기화를 처리하고 다시 지정을 수행할 수 있습니다.

예외 AnyException의 특수 유형은 예외를 발견하는 데 사용할 수 있으며 ANY 기본 유형과 같습니다. AnyException의 레코드 변수를 선언하고 EGL이 예외를 처리하는 경우 변수가 실제 예외 레코드의 유형을 사용합니다. 다음 예제를 고려하십시오.
try
  get next mySerialRecord
onException(myEx AnyException)
  myErrorHandler(myEx);
end
EGL이 FileIOException을 처리할 때 따르려는 특정 코드 경로가 있는 경우 다음과 같이 특수 검사를 추가할 수 있습니다.
try
  get next mySerialRecord
onException(myEx FileIOException)
   myErrorHandler1(myEx);
onException(myEx AnyException)
  myErrorHandler2(myEx);
end

여기서 myErrorHandler2()는 FileIOException이 아닌 다른 예외를 처리합니다.

EGL이 예외를 처리하지만 onException 블록이 예외를 발견하지 않는 경우 함수가 즉시 종료되고 제어가 오류를 처리하는 함수를 호출한 함수로 돌아갑니다. 이런 방법으로, EGL은 기능이 onException 블록과 함께 예외를 발견하거나 예외가 기본 기능에 도달할 때까지 예외를 전달합니다. 기본 기능이 예외를 발견하는 데 실패하는 경우 프로그램이 즉시 종료되고 로그에 예외의 메시지 필드를 작성합니다. 원격으로 호출한 프로그램에서 예외가 발생하는 경우 호출 프로그램이 원래 예외가 아닌 InvocationException을 수신합니다. 마찬가지로, 서비스 기능의 예외가 ServiceInvocationException을 호출 프로그램에 전달합니다.

다시 말하면 다음 예제에서와 같이 함수는 호출하는 함수에서 발생한 예외를 발견할 수 있습니다.
function FuncOne(myRec serialRecordType)
  try
    FuncTwo(myRec);
  onException(myEx AnyException)
    myErrorHandler2(myEx);
  endend
function FuncTwo(myRec serialRecordType)
  get next myRec;
end
예외는 아래에서 설명된 V6 예외 호환성 모드에서와 마찬가지로 함수에서 함수로 전달되지 않습니다.

하드 및 소프트 I/O 오류

파일에 작성하거나 읽고 있는 경우 EGL이 하드소프트 I/O 오류 간의 차이를 작성합니다. 다음 오류는 소프트, 즉, 데이터 손실의 원인이 아닌 것으로 간주됩니다.

표 1. 소프트 I/O 오류
오류 의미
중복 색인화된 레코드 또는 상대 레코드의 경우 이 오류는 두 번째 레코드에 동일한 키가 있음을 표시합니다.
endOfFile 일련화, 색인화된 레코드 또는 상대 레코드의 경우, 이 오류는 파일의 끝을 지나 읽으려고 시도했음을 표시합니다.
noRecordFound 레코드 유형의 경우 오류는 찾을 수 없는 레코드를 읽으려는 시도를 표시합니다.

올바르지 않은 파일 형식 또는 전체 파일과 같은 기타 오류는 하드 오류로 간주됩니다. 색인화된 파일, 상대 파일 또는 연속 파일에 대한 하드 I/O 오류는 FileIOException을 처리합니다. SQL 데이터베이스에 대한 하드 I/O 오류는 SQLException을 처리합니다.

소프트 I/O 오류는 오류 값을 레코드와 연관시키지만 예외가 처리되도록 하지는 않습니다. 이 상황을 테스트하려면 is 또는 not 연산자를 사용하십시오. 해당 연산자를 사용하기 위해 시도 블록의 질문 내에 I/O 문을 배치할 필요는 없습니다. 그러나 시도 블록 내에 I/O 문을 넣지 않는 경우 하드 I/O 오류를 동시에 확인할 수 없습니다.
while(TRUE)  // 무한 반복
  try
    get next mySerialRecord;
    if(mySerialRecord is endOfFile)
      exit while;
    end  onException(myEx AnyException)
    myErrorHandler(myEx);
  endend

throwNrfEofExceptions 특성

기본적으로 throwNrfEofExceptions 프로그램 특성은 아니오로 설정되며 이는 다음 예제에서와 마찬가지로 시도 블록의 외부에서 오류가 발생하는 경우에도 소프트 I/O 오류 noRecordFoundendOfFile 후에 프로그램이 계속됨을 의미합니다.
get myCustomer;
if(myCustomer is noRecordFound)
   add myCustomer;
end
그러나 이러한 오류 중 하나가 발생하면 EGL이 예외를 처리하도록 하는 것을 선호할 수 있습니다. throwNrfEofExceptions 프로그램 특성을 예로 설정하여 이를 수행할 수 있습니다. 해당 경우 EGL은 다음 예외 중 하나를 처리합니다.
  • 파일 I/O를 수행 중인 경우 EGL이 RuntimeException을 처리합니다.
  • SQL I/O를 수행 중인 경우 EGL이 SQLException을 처리합니다.
시도 블록에서 이 오류를 발견해야 하며 그렇지 않으면 프로그램이 종료됩니다. 이전 예제를 사용하여 get 문에 대한 레코드를 찾을 수 없는 경우 프로그램이 종료됩니다. 그러나 다음 기술로 예외를 처리할 수 있습니다.
  • 소프트 오류 후에 계속:
    try
      get myCustomer; 
    end
    if (myCustomer is noRecordFound) 
      add myCustomer; 
    end
  • 선호 기술인 예외 발견:
    try
      get myCustomer; 
    onException (myEx FileIOException)
      if (myCustomer is noRecordFound) 
        add myCustomer; 
      else
        myErrorHandler(myEx);
      endend

고유한 예외 처리

EGL throw 문을 사용하여 사전 정의된 시스템 예외를 처리할 수 있습니다. 예외 처리에서와 같이 레코드를 기반으로 변수를 선언해야 합니다.
nullEx NullValueException{};
 ... 
throw nullEx;
시스템이 정의하는 예외 외에도 고유한 예외 레코드를 작성할 수 있습니다. 다른 레코드와 마찬가지로, 레코드 파트를 먼저 정의해야 하고 그 다음에 이를 기반으로 변수를 선언해야 합니다.
Record CustomerException type Exception
  customerNumber INT;
end ... 
throw new customerException {
  customerNumber = custNum,
  message = "Illegal customer number" };
이와 같이 사용자 정의 예외 레코드는 시스템 예외 레코드와 같은 messageID메시지 필드를 자동으로 포함합니다.

V6 예외 호환성

이전 버전과의 호환경의 경우 버전 6 EGL의 오류 처리 메소드를 계속 사용할 수 있습니다.

프로그램의 v60ExceptionCompatibility 특성을 예로 설정하는 경우 프로그램별 기초에서 V6 예외 모드를 지정합니다. 그러나 최상의 결과를 위해 사용자의 모든 프로그램에 동일한 설정을 사용하십시오.

V6 예외는 일반적으로 시도 블록을 통해 처리됩니다. 차이점은 V6 예외는 단일 onException 문만 허용하고 예외 유형을 지정하지 않는다는 점입니다. 동작은 또한 onException 문에 내재된 AnyException 수정자가 있는 경우와 동일합니다.
try
  posNum = abs(myVar);
onException
  if(sysVar.errorCode = "00000008") // 올바르지 않은 입력
    myErrorHandler1();
  if(sysVar.errorCode = "00000012") // 값을 지정할 수 없음
    myErrorHandler2();
  else
    myErrorHandler3();
end
예외 레코드를 기반으로 하는 대신 V6 예외 호환성은 sysVar.errorCode 시스템 변수에 의존합니다. V6 예외 모드에서 실행 중인 경우 sysVar.errorCode는 다음 경우에서 설정됩니다.
  • call 문의 완료 시
  • 서비스에 대한 호출 후
  • get 또는 replace와 같은 파일 I/O 문 뒤
  • 다수의 EGL 시스템 기능 호출 후
또한 SQL I/O 오류의 경우 V6 예외 호환성은 sysVar.sqlData의 시스템 변수에 의존합니다.
vgVar.handleSysLibraryErrors 시스템 변수(시스템 라이브러리의 함수에 대해) 또는 vgVar.handleHardIOErrors(파일 및 SQL I/O에 대해)가 1로 설정된 경우 try 블록이 V6 예외 모드에서 sysVar.errorCode에 액세스할 필요가 없습니다.
vgVar.handleSysLibraryErrors = 1;
posNum = abs(myVar);
if(sysVar.errorCode == "00000008") // 올바르지 않은 입력
  myErrorHandler1();
else
  if(sysVar.errorCode == "00000012") // 지정할 수 없음
    myErrorHandler2();
  else
    exit program (-1);
  endend

그러나 vgVar.handleSysLibraryErrors가 0(기본값)으로 설정되고 시도 블록을 사용하여 예외를 발견하지 않는 경우 예외로 인해 프로그램이 종료됩니다.

자세한 정보는 예외 핸들링의 내용을 참조하십시오.