티스토리 뷰
함수의 초기화 과정에서 종종 goto문을 사용하곤 한다.
예를 들면 열 가지 정도의 변수에 메모리를 할당 해 주는데, 다섯번째쯤 되는 변수를 처리하는 과정에서 오류가 발생했다고 가정해보자.
그럼 앞에 메모리가 할당된 네 개의 변수는 어떻게 될까?
할당해놓고 해제해 준 적이 없으니 메모리 누수상태가 된다. (Memory Leak)
그래서 변수 처리중에 에러가 발생 하면, 바로 return을 해버리는게 아니라 goto문을 이용하여 error 처리부로 이동시켜 메모리 해제해주는 작업을 거치게 된다.
윈도우에서 제공하는 try-finally 와 유사하다고 보면된다.
goto문을 사용하는 간단한 예제는 다음과 같다.
int Initialize()
{
// 이 예제에서는 CDialog라는 클래스가 있다고 가정한다.
CDialog *dlgA;
CDialog *dlgB;
CDialog *dlgC;
dlgA = new CDialog;
if( dlgA->InitDialog() < 0 ) // Error 발생시,
{
goto _error;
}
dlgB = new CDialog;
if( dlgB->InitDialog() < 0 ) // Error 발생시,
{
goto _error;
}
dlgC = new CDialog;
if( dlgC->InitDialog() < 0 ) // Error 발생시,
{
goto _error;
}
// no error
return 0;
_error:
if( dlgA != NULL )
{
delete dlgA;
dlgA = NULL;
}
if( dlgB != NULL )
{
delete dlgB;
dlgB = NULL;
}
if( dlgC != NULL )
{
delete dlgC;
dlgC = NULL;
}
return -1;
}
goto문에서 컴파일 에러가 나요
제목은 goto문 에러에 관한 내용인데, goto문을 설명하는데 너무 많은 시간과 지면을 할당했다.
암튼, 가끔 goto를 잘 쓰다가도 이런 컴파일 에러를 만날 수 있다.
jump to label _error [-fpermissve]
_error 자리에는 goto할 레이블의 이름이 들어간다.
왜 생길까?
C언어 시절 변수 선언을 생각 해 보자.
C언어 시절에는 모든 변수의 선언은 블럭의 최상단에 했어야 했다.
블럭이란 { } 로 감싸진 코드블럭을 말한다.
하지만 C++로 들어와서는 블럭의 최상단이 아닌 어디에서도 변수의 선언을 할 수 있게 되었다.
다음 코드 예제를 보도록 하자
int func()
{
int a; // c, c++ 모두 가능
a = 3;
int b = 2; // c 오류, c++ 가능
if( a > b )
{
int res; // c, c++ 모두 가능
res = a - b;
int res2; // c 오류, c++ 가능
{
int res3; // c, c++ 모두 가능
}
for( int i = 0; i < b; i++) // c 오류, c++ 가능
{
printf("%d\n", i);
}
}
return 0;
}
이렇게 변수의 선언에 관한 C, C++문법의 차이를 열심히 설명하는 이유.
goto는 C Style로 변수 선언을 하면 에러가 나지 않는다.
즉, 최소한 goto 이하에 C++형식으로 변수가 선언된 흔적이 없어야 한다.
<goto 에러 형태>
int Initialize()
{
CDialog *dlgA;
CDialog *dlgB;
digA = new Dialog;
if( digA->InitDialog() < 0 )
{
goto _error;
}
// c++형식의 변수 선언을 했기 때문에 에러가 발생한다.
bool bShown = digA->isShow();
if( bShown == true )
{
goto _error;
}
if( digB->InitDialog() < 0 )
{
goto _error;
}
return 0;
_error:
if( dlgA != NULL )
{
delete dlgA;
dlgA = NULL;
}
if( dlgB != NULL )
{
delete dlgB;
dlgB = NULL;
}
return -1;
}
<에러 우회 방법>
int Initialize()
{
CDialog *dlgA;
CDialog *dlgB;
digA = new Dialog;
if( digA->InitDialog() < 0 )
{
goto _error;
}
// c에서도 가능한 변수 선언 형태로 만들어주면 된다.
// 단, 이 때 변수의 생명력(?)은 블럭 내부에 한정된다.
{
bool bShown = digA->isShow();
if( bShown == true )
{
goto _error;
}
}
if( digB->InitDialog() < 0 )
{
goto _error;
}
return 0;
_error:
if( dlgA != NULL )
{
delete dlgA;
dlgA = NULL;
}
if( dlgB != NULL )
{
delete dlgB;
dlgB = NULL;
}
return -1;
}
사실 goto가 C언어용 문법이라서 에러가 나는건 아니다.
goto의 특성 자체가 코드의 위, 아래 영역을 자유롭게 넘나드는 형태인데, 넘나드는 그 사이 영역에 변수가 새로 할당되는 동작이 있거나 하면 문법상 오류가 날 수 있다.
goto문 이후 변수를 할당해주었고, goto된 레이블로 이동 후 해당 변수를 사용할 수 있을까? 없을까? 컴파일러는 과연 이 사실을 알 고 있을까?
그래서 컴파일러가 goto문 아래로 변수 선언을 못하게 막은것 아닐까?
C Style 변수 선언을 하면 절대 오류가 나지 않기 때문에, 알기 쉽게 그렇게 설명한 것 뿐이다. :)
'C, C++ > C, C++' 카테고리의 다른 글
atoi(), itoa() 함수에 대하여.. (12) | 2014.03.03 |
---|---|
c언어 매크로 사용법 - 2. 가변인자 매크로 (0) | 2014.03.02 |
c언어 매크로 사용법 - #, ## 연산자 (2) | 2014.03.02 |
C언어 bsearch() - 이진탐색 함수 (0) | 2014.02.16 |
C언어 가변인자(가변파라미터)를 사용해보자 (7) | 2014.01.25 |
- Total
- Today
- Yesterday
- ZONES
- NgZone
- ECMA2015
- 타입스크립트
- ansi color
- 안시 컬러
- angular2
- 폰트 조정
- 안시 색상
- Rx.js
- git proxy
- C언어
- lua table
- observable
- 우분투 16.04
- Swift
- git 설정
- JavaScript
- Zone.js
- 스위프트
- Angular
- QT
- typeScript
- qemu linux arm
- 리눅스 터미널 색상
- vim
- 챗봇
- itoa
- zone
- terminal 색
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |