pure call error

pure call error 라는걸 주워들었다.

그게뭐지?하고 찾아보게 된 글

코드는 여기 참고

https://iamskylover.tistory.com/90

코드 전문

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
31
32
33
34
35
36
37
38
#include "stdio.h"

class A
{
public:
    A() {
    }

    void intermediate_call() {
        // Bad: virtual function call during object destruction
        virtual_function();
    }

    virtual void virtual_function() = 0;

    virtual ~A() {
        intermediate_call();
    }
};

class B : public A
{
public:
    void virtual_function()
    {
        printf("B::virtual_function called\n");
    }
};


int main()
{

    B myObject;

    myObject.virtual_function();
    return 0;
}

해당 코드를 실행하면 pure call error 가 나는걸 알 수 있는데

Untitled

일반적인 호출

Untitled

A 소멸자에서의 호출

Untitled

보면 virtual table이 가르키는 주소가체가 다르다

해당 코드를 조금더 들여다보면 rcx 에 B의 vftable 값을 씌운다

Untitled

A class 소멸자에서도 a의 vftable 주소를 가르키게 세팅한다는것을 알 수 있다.

Untitled

그래서 생각할 수 있는게

class a의 생성자, 소멸자에서는 class a의 가상 함수만 호출을 한다.

Untitled

A class의 순수가상함수는 purecall이라는 곳을 가르킨다

Untitled

release 에서도 해당방식으로 작동한다.

Untitled

그래서 든생각

A → B → C 식으로 상속해서

각각의 상속받는 함수를 만들면 소멸자에서 각각 클래스에 해당하는 함수를 호출 할 수도 있겠구나.

A 소멸자에서 호출하는건 뿌서지니 빼고 B를 상속받는 C클래스를 추가로 만들어서 테스트 해봤다.

Untitled

생각한대로 작동한다. 뭔가 연쇄 책임 패턴을 보는거같기도..

사실 딱 기억할거는 한가지다.

생성자 소멸자에서 구현되지않은 순수가상함수를 호출하면 안된다.

사실 한번 겪어보면 알게 될 얘기기도 하지만..

그런데 링크의 화면을보면 프로그램이 잘못된 메모리를 참조해 crash 난것이 아닌, 명백하게 pure call error라는것을 인지하고 있다는 것이다. 참고로 테스트해본 컴퓨터에서는 abort() 호출로 인한 종료로 처리되었다.

콜스택으로도 확인할 수 있다.

Untitled

그래서 아 이부분은 컴파일러마다 다르구나. 라는것을 알 수 있는데 windows 의 경우엔 이렇게 처리하는 것이다.

오 그럼 이부분에 대해서 referecce로 어떻게 처리하라고 명시되어있지 않을까 싶어서 찾아봤다.

https://en.cppreference.com/w/cpp/language/abstract_class

Making a virtual call to a pure virtual function from a constructor or the destructor of the abstract class is undefined behavior (regardless of whether it has a definition or not).

UB란다

그럼 msvc같은경우는 어떻게 처리하는가에 대해 찾아보면

기본적으로 프로세스를 종료시킨다.

1
2
_get_purecall_handler
_set_purecall_handler

Exception Handler 와 비슷하게 purecall 에대해서 원하는 함수를 세팅해서 호출 할 수도 있다.

Posted 2023-04-15