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 가 나는걸 알 수 있는데
일반적인 호출
A 소멸자에서의 호출
보면 virtual table이 가르키는 주소가체가 다르다
해당 코드를 조금더 들여다보면 rcx 에 B의 vftable 값을 씌운다
A class 소멸자에서도 a의 vftable 주소를 가르키게 세팅한다는것을 알 수 있다.
그래서 생각할 수 있는게
class a의 생성자, 소멸자에서는 class a의 가상 함수만 호출을 한다.
A class의 순수가상함수는 purecall이라는 곳을 가르킨다
release 에서도 해당방식으로 작동한다.
그래서 든생각
A → B → C 식으로 상속해서
각각의 상속받는 함수를 만들면 소멸자에서 각각 클래스에 해당하는 함수를 호출 할 수도 있겠구나.
A 소멸자에서 호출하는건 뿌서지니 빼고 B를 상속받는 C클래스를 추가로 만들어서 테스트 해봤다.
생각한대로 작동한다. 뭔가 연쇄 책임 패턴을 보는거같기도..
사실 딱 기억할거는 한가지다.
생성자 소멸자에서 구현되지않은 순수가상함수를 호출하면 안된다.
사실 한번 겪어보면 알게 될 얘기기도 하지만..
그런데 링크의 화면을보면 프로그램이 잘못된 메모리를 참조해 crash 난것이 아닌, 명백하게 pure call error라는것을 인지하고 있다는 것이다. 참고로 테스트해본 컴퓨터에서는 abort() 호출로 인한 종료로 처리되었다.
콜스택으로도 확인할 수 있다.
그래서 아 이부분은 컴파일러마다 다르구나. 라는것을 알 수 있는데 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같은경우는 어떻게 처리하는가에 대해 찾아보면
- https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/purecall?view=msvc-170
- https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/get-purecall-handler-set-purecall-handler?view=msvc-170
기본적으로 프로세스를 종료시킨다.
1
2
_get_purecall_handler
_set_purecall_handler
Exception Handler 와 비슷하게 purecall 에대해서 원하는 함수를 세팅해서 호출 할 수도 있다.