R6025 런타임 에러

@codemaru · October 03, 2007 · 3 min read

R6025        md 0

이런 런타임 오류를 접해보신 적이 있으신가요?
아래 코드를 실행하면 위와 같은 오류가 발생합니다.
몇 해 전에 작성한 글들을 보니 R6025를 R605라고 잘못 적어뒀더군요. 헐 ㅠㅠ

class CBase;  
class CDerived;  
void func(CBase \*p);  
  
class CBase  
{  
public:  
    CBase() { func(this); }  
    virtual void test() = 0;  
};  
  
class CDerived : public CBase  
{  
public:  
    void test()  
    {  
        printf("hello\n");  
    }  
};  
  
void func(CBase \*p)  
{  
    p->test();  
}  
  
int \_tmain(int argc, \_TCHAR\* argv[])  
{  
    CDerived a;  
    return 0;  
}

코드를 잠시 설명해 보겠습니다.
CDerived는 CBase를 상속받은 클래스입니다. CBase에는 test라는 순수 가상함수가 있습니다. main에서 CDerived 클래스를 호출하고 있습니다. 이 호출을 따라가면서 함수 호출 순서를 한번 그려 봅시다.

CDerived 생성자 => CBase 생성자 => func(this) => this->test

위와 같이 되겠죠. 중요한 것은 마지막에 호출되는 this->test 함수 입니다. 처음 생성하려고 의도했던 객체는 CDerived 입니다. 하지만 CDerived는 아직 완전하게 생성된게 아니죠. CBase 생성자가 리턴하지 않았기 때문입니다. 따라서 여기서 this->test는 CBase의 순수 가상 함수인 test를 호출합니다. 그래서 런타임 오류를 발생하는 것이죠.

예제가 너무 작위적이기 때문에 이런 바보같은 코드를 누가 작성하겠어? 라고 반문하실 수도 있습니다. 하지만 생성자를 통해서 뭔가를 하는 코드를 작성하는 경우라면 언제든지 실수를 할 수 있는 부분입니다. 저 또한 예전에 워커 스레드 래퍼 클래스를 작성할 때 이런 실수를 한 적이 있습니다. 따라서 클래스를 설계할 때 생성자는 항상 주의 해야 하겠습니다. 가장 좋은 방법은 생성자에서 가상 함수를 호출하지 않도록 하는 것 입니다.

보다 자세한 설명은 아래 MS 기술 자료에서 얻으실 수 있습니다.
http://support.microsoft.com/?kbid=125749

@codemaru
돌아보니 좋은 날도 있었고, 나쁜 날도 있었다. 그런 나의 모든 소소한 일상과 배움을 기록한다. 여기에 기록된 모든 내용은 한 개인의 관점이고 의견이다. 내가 속한 조직과는 1도 상관이 없다.
(C) 2001 YoungJin Shin, 0일째 운영 중