Main Content

예외에 대한 대응책

개요

MATLAB®은 기본적으로 예외가 발생할 때 현재 실행 중인 프로그램을 종료합니다. 그러나 프로그램에서 예외를 포착하는 경우, 문제가 무엇인지에 대한 정보를 캡처하고 그 특정 조건에 적절한 방식으로 처리할 수 있습니다. 이를 위해서는 try/catch 문이 필요합니다.

try/catch 문

원치 않는 결과를 생성할 수 있는 명령문이 코드에 있는 경우, 오류를 포착하고 이를 적절하게 처리하는 try/catch 블록에 이러한 명령문을 넣습니다.

try/catch 문은 다음 의사코드와 비슷한 모양으로 표시됩니다. 이 명령문은 다음 두 부분으로 구성됩니다.

  • try 문과 catch 문 사이의 모든 라인을 포함하는 try 블록.

  • catch 문과 end 문 사이의 모든 코드 라인을 포함하는 catch 블록.

    try
       Perform one ...
          or more operations
A   catch ME
       Examine error info in exception object ME
       Attempt to figure out what went wrong
       Either attempt to recover, or clean up and abort
    end

B   Program continues

프로그램은 try 블록에 있는 명령문을 실행합니다. 오류를 발견하면 try 블록의 나머지 명령문을 모두 건너뛰고 catch 블록의 시작 부분(여기서는 A로 표시된 지점)으로 이동합니다. try 블록의 모든 작업을 성공적으로 완수하는 경우에는 catch 블록 전체를 건너뛰고 end 문 다음의 첫 번째 라인(B로 표시된 지점)으로 이동합니다.

try, catch, end 명령과 try 블록과 catch 블록의 코드는 서로 별도의 라인에 지정하는 것이 좋습니다. 이러한 요소들을 같은 라인에 함께 지정할 경우에는 다음과 같이 쉼표로 구분하십시오.

try, surf, catch ME, ME.stack, end
ans = 
    file: 'matlabroot\toolbox\matlab\graph3d\surf.m'
    name: 'surf'
    line: 49

참고

try 또는 catch 블록 내에서는 중첩 함수를 정의할 수 없습니다.

try 블록

실행 시, 코드는 try 블록으로 진입하여 블록 내의 각 명령문을 정규 프로그램의 일부인 것처럼 실행합니다. 오류가 발견되지 않으면 MATLAB은 catch 블록 전체를 건너뛰고 end 문 다음부터 실행을 계속합니다. try 블록 내의 명령문이 하나라도 실패할 경우 MATLAB은 블록 내의 나머지 명령문을 실행하지 않고 즉시 try 블록에서 나와 catch 블록으로 진입합니다.

catch 블록

catch 명령은 catch 블록의 시작 위치를 표시하고, 예외를 일으킨 원인에 대한 정보가 포함된 데이터 구조체에 액세스할 수 있게 해 줍니다. 위에 나온 의사코드에서, 이 데이터 구조체는 변수 ME로 표시되어 있습니다. MEMException 객체입니다. 예외가 발생할 경우 MATLAB은 MException 객체를 생성하여 이 오류를 처리하는 catch 문에 이 객체를 반환합니다.

catch 문에는 어떠한 인수도 지정할 필요가 없습니다. MException 객체에서 제공되는 정보나 메서드가 필요하지 않은 경우 catch 키워드만 지정하면 됩니다.

MException 객체는 오류가 발생한 프로그램의 내부 코드에 의해 생성됩니다. 이 객체는 발생한 문제와 진행 방법을 파악하는 데 유용할 수 있는, 오류에 대한 정보가 포함된 속성을 갖습니다. MException 객체는 또한 예외에 대응할 수 있게 해 주는 메서드에 대한 액세스를 제공합니다.

catch 블록으로 진입한 후, MATLAB은 명령문을 차례로 실행합니다. 이러한 명령문은 다음을 시도할 수 있습니다.

  • 오류를 해결합니다.

  • 오류에 대한 추가 정보를 캡처합니다.

  • MException 객체에 있는 정보를 확인하고 적절하게 대응합니다.

  • 오류가 발생한 코드로 인해 방치된 환경을 정리합니다.

catch 블록은 종종 rethrow 명령으로 끝납니다. rethrow는 MATLAB이 현재 함수를 종료하고, 예외가 처음 발생했을 때의 호출 스택 정보를 유지하도록 합니다. 이 함수가 최상위 수준에 있는 경우, 즉 다른 함수에 의해 호출되지 않았으면 프로그램은 종료됩니다. 실패한 함수가 다른 함수에 의해 호출된 경우에는 호출한 함수로 돌아갑니다. 이러한 호출이 더 상위 수준의 try 블록 내에서 발생하지 않은 경우, 프로그램 실행은 계속해서 더 상위 수준의 함수로 돌아갑니다. 이 호출이 더 상위 수준의 try 블록 내에서 발생한 경우 프로그램은 해당 catch 블록을 실행합니다.

예외 처리 방법에 대한 제안 사항

다음 예제는 이미지 파일의 내용을 읽습니다. 이 예제는 세부적인 오류 처리 정보를 포함하고 있으며 오류에 대해 수행할 수 있는 제안된 조치를 보여줍니다.

이미지 읽기 함수는 여러 가지 방법으로 오류를 발생시키고 포착합니다.

  • 첫 번째 if 문은 함수가 입력 인수를 사용하여 호출되었는지 확인합니다. 입력 인수가 지정되지 않은 경우 프로그램은 오류를 발생시키고 오류를 해결하기 위해 입력 인수를 제안합니다.

  • try 블록은 파일을 열고 읽으려고 시도합니다. 열기나 읽기에 실패할 경우 프로그램은 결과로 생성된 예외를 포착하고 변수 ME1MException 객체를 저장합니다.

  • catch 블록은 지정된 파일을 찾을 수 없는지 여부를 확인합니다. 파일을 찾을 수 없는 경우, 프로그램은 파일 이름 확장자의 흔한 변형(예: jpg 대신 jpeg)이 사용되었을 가능성을 고려해서 수정된 확장자를 사용하여 작업을 다시 시도합니다. 이 작업은 원래 try/catch 문 내에 중첩된 try/catch 문을 사용하여 수행합니다.

function d_in = read_image(filename)

% Check the number of input arguments.
if nargin < 1
    me = MException('MATLAB:notEnoughInputs','Not enough input arguments.');
    aac = matlab.lang.correction.AppendArgumentsCorrection('"image.png"');
    me = me.addCorrection(aac);
    throw(me);
end

% Attempt to read file and catch an exception if it arises.
try
   fid = fopen(filename,'r'); 
   d_in = fread(fid); 
catch ME1 
   % Get last segment of the error identifier.
   idSegLast = regexp(ME1.identifier,'(?<=:)\w+$','match'); 

   % Did the read fail because the file could not be found? 
   if strcmp(idSegLast,'InvalidFid') && ...
      ~exist(filename,'file')

      % Yes. Try modifying the filename extension.
      switch ext
      case '.jpg'    % Change jpg to jpeg 
          filename = strrep(filename,'.jpg','.jpeg');
      case '.jpeg'   % Change jpeg to jpg 
          filename = strrep(filename,'.jpeg','.jpg');
      case '.tif'    % Change tif to tiff 
          filename = strrep(filename,'.tif','.tiff');
      case '.tiff'   % Change tiff to tif 
          filename = strrep(filename,'.tiff','.tif');
      otherwise 
         fprintf('File %s not found\n',filename);
         rethrow(ME1);
      end 

      % Try again, with modified filenames.
      try
         fid = fopen(filename,'r'); 
         d_in = fread(fid);
      catch ME2
         fprintf('Unable to access file %s\n',filename);
         ME2 = addCause(ME2,ME1);
         rethrow(ME2)
      end 
   end 
end

위 예제에서는 예외에 대응하여 수행할 수 있는 다음과 같은 작업에 대해 다루었습니다.

  • MException 객체의 identifier 필드를 발생할 수 있는 오류의 원인과 비교합니다. 이 경우 함수는 파일을 찾을 수 없음을 나타내는 'InvalidFid'로 식별자가 끝나는지 확인합니다.

  • 중첩 try/catch 문을 사용하여 개선된 입력값으로 작업을 다시 시도합니다. 이 경우 함수는 파일 이름 확장자의 알려진 변형을 사용해 열기 및 읽기 작업을 다시 시도합니다.

  • 적절한 메시지를 표시합니다.

  • 첫 번째 MException 객체를 두 번째 객체의 cause 필드에 추가합니다.

  • 제안 정정 사항을 MException 객체에 추가합니다.

  • 예외를 다시 발생시킵니다. 그러면 프로그램 실행이 중지되고 오류 메시지가 표시됩니다.

오류로 인해 발생한 원치 않는 결과를 정리하는 것도 좋은 생각입니다. 예를 들어, 오류가 발생한 후 열린 상태로 남아 있는 Figure를 닫아 보십시오.