본문 바로가기

컴퓨터/디버깅

명확하지 않게 다가오는 컴파일 에러 메세지들과 그 뜻

글에 대한 공지 만약 검색 엔진에 컴파일 에러 메세지를 입력하여 이 글을 읽게 되었다면, 에러 메세지와, 에러가 난 코드를 답글로 달아 주세요. 같이 풀어 봅시다.


   컴파일러의 에러 메세지를 보고 그 원인을 곧바로 생각하기가 가끔 어려울 때가 있다. 하지만 에러가 난 곳을 제대로 찾거나 조금만 들여다 보면 물론 컴파일러 제작자들의 노고에 감사하지 않을 수 없을만큼 에러 메세지의 의미가 명확해 지는데, 이 글은 그와 같은 경우들에 대해서 살펴 보도록 한다. 내가 작업하며서 만나게 될 그와 같은 경우들을 정리하는 것이기 때문에 꽤 오랜 기간에 걸쳐 추가/수정이 이루어질 것으로 생각하고 있다.

사용 컴파일러에 대한 표시는 다음을 따른다.
VC6 : Visual Studio 6.0
VC9 : Visual Studio 2008
gcc : gcc



다음과 같은 에러 메세지가 떴다 (VC9).

1>.\PerfusionCalculator.cpp(386) : error C2761: 'bool CPerfusionCalculator::cross_over(ICGPerfusion::PerfParam *,const ICGPerfusion::PerfParam &) const' : member function redeclaration not allowed

실제로 에러가 난 줄의 코드는 다음과 같다.

bool CPerfusionCalculator::cross_over(ICGPerfusion::PerfParam* variant, const ICGPerfusion::PerfParam& old_param) const;


에러 메세지의 의미: CPerfusionCalculator::cross_over 라는 member function 을 재선언 할 수 없다는 것이다. 저 멤버 함수는 virtual 도 아니고, CPerfusionCalculator 는 상속된 클래스도 아닌데 함수를 재선언하려고 한다는 것이다. 왜 이런 일이 발생했을까?

에러의 원인 : 컴파일러의 에러 메세지를 잘 보면 에러가 난 파일은 cpp 파일이다.  일반적으로 함수의 선언은 헤더 파일에서 하는데, 지금 cpp 파일 안에서 함수를 선언하고 있으며, 그것도 virtual 이 아닌 함수를 그렇게 하고 있다. 자, 단순한 텍스트인 소스를 보고 컴파일러가 함수의 정의와 선언을 구별할 수 있는 방법은 무엇일까? 그것은 바로 함수의 선언은 함수 prototype 뒤에 ; 가 있고, 함수의 정의는 함수 prototype 뒤에 { 가 온다는 것일 것이다. 따라서 위의 경우, cpp 파일에서 프로그래머(나 -.-ㅋ)는 '정의'를 하려고 했는데 뭔가 잘못되어서 '선언'이 되어버렸고, 그것은 적절치 않은 선언이었던 것이다. 다시 에러가 난 코드를 보면,

bool CPerfusionCalculator::cross_over(ICGPerfusion::PerfParam* variant, const ICGPerfusion::PerfParam& old_param) const;
{
   ...


제일 뒤에 ; 가 있는 것이 보인다. h 파일에서 C&CP 를 하고 ; 를 지웠어야 하는데 지우지 않았던 것이다.
- 끝.




다음과 같은 에러 메세지가 떴다(VC9)


"지원되지 않는 작업을 시도했습니다." 라는 문구가 나타났는데, 이것은 주로 DDX 로 연결되어 있는 컨트롤을 삭제했을 경우, DDX로 연결하는 부분은 삭제가 되지 않고 남아 있을 때 발생한다. 즉, dialog-template 에서 resource editor 에서 컨트롤을 지웠으면 그 컨트롤에 연결된 DDX 부분이 코드에서 삭제되어야 함에도 불구하고 자동으로 삭제되지 않으면 DDX로 없는 컨트롤을 연결시키려 하기 때문에 위와 같은 에러가 발생한다.

따라서 다음과 같이 해결한다.
1. DDX로 연결하는 부분으로 가서 없어진 컨트롤과 연결시키는 부분을 없앤다.

void CPerfusionCalculatorDLG::DoDataExchange(CDataExchange* pDX)

{

    CDialog::DoDataExchange(pDX);

    DDX_Control(pDX, IDC_BTN_IMAGE_DATA_PATH, _btnImageDataPath);

    DDX_Control(pDX, IDC_EDT_IMAGE_DATA_PATH, _edtImageDataPath);

    DDX_Control(pDX, IDC_BTN_MAKE_RID, _btnMakeRID);

    DDX_Control(pDX, IDC_BTN_CALCULATE_PR, _btnCalculatePR);

    DDX_Control(pDX, IDC_LIST1, _lcDataReport);

    DDX_Control(pDX, IDC_LC_REPORT2, _lcReport);

    DDX_Control(pDX, IDC_TB_RID_IMAGE, _tabRID);

    DDX_Control(pDX, IDC_BTN_CHANGE_ONSET_TIME, _btnChangeOnsetTime);

    DDX_Control(pDX, IDC_SLD_MAX_RID_TIME_DRAW, _sldMaxRIDTimeDraw);

    DDX_Control(pDX, IDC_CMB_DRAW_MODE, _cmbRIDDrawMode);

    DDX_Control(pDX, IDC_CHK_MAKE_PERF_MAP, _chkMakePerfMap);//이 줄이 없어져야 함.

}


2. 문제가 생기는 것은 아니지만 컨트롤 변수도 없애자.

protected:

    // If not set, skip making perfusion map while calculating perfusion rate.

    CButton _chkMakePerfMap; // 이 변수는 지워진 컨트롤에 연결되었던 변수이다.