인프런 커뮤니티 질문&답변

작성자 없음

작성자 정보가 삭제된 글입니다.

[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part1: C++ 프로그래밍 입문

디버깅 문제 풀이 #3

virtual 과 에러에 대한 질문이 있습니다.

24.06.19 16:29 작성

·

156

·

수정됨

0

exercise_A 문제풀이를 하면서 knight 를 delete 했음에도 불구하고 player타입으로는 해당 메모리를 접근할 수 있다는것에 충격먹어 virtual에 대해 궁금한게 생겨 이것저것 시도해보고 있습니다.


#include <iostream>
using namespace std;

class AA
{
public:
    int _Aa = 10;

public:
    void Info()
    {

        cout << "AA의 _Aa : " << _Aa << endl;
    }
    void Set()
    {
        cout<< "test" << endl;
    }
};
class BB : public AA
{
public:
    int _Ba = 44;

public:
    virtual void Info()
    {

        cout << "BB의 _Aa : " << _Aa << endl;
    }
};
int main()
{

	AA* A1 = new BB();

	AA* A2 = A1;

	delete A1;   // BB클래스의 void Info() 에 virtual을 붙이면 왜 중단점 에러가 발생?
	A1 = nullptr;

    A2->Info();


}

delete A1; 부분에서

 

"중단점 명령(__debugbreak() 문 또는 유사한 호출)이 ConsoleApplication38.exe에서 실행되었습니다."

 

라는 에러가 뜹니다.

 

BB 클래스의  void Info() 함수에 virtual 을 붙인 이후로 이러한 에러가 뜨는데, 저 위치에 vitrual을 붙인 것이 왜 이러한 에러를 유발하는지 궁금합니다.

 

만약 virtual을 AA 클래스의 Info() 함수에 붙인다면, 'A2->Info();' 부분에서 BB 클래스의 Info() 함수를 호출하게 되므로 메모리 엑세스 위반까지는 이해를 했으나, virtual이 BB 클래스의 Info() 함수에 붙일 경우에는 delete A1; 부분에서 왜 에러가 뜨는지 알고싶습니다.



답변 3

0

저엉님의 프로필 이미지

2024. 06. 23. 17:41

같이 공부하는 사람입니다.. 저도 궁금해서 확인해봤는데요

클래스 BB에서 Info를 가상함수로 등록하면서 BB클래스의 객체를 생성할 때 가상함수 테이블이 생성되고, (AA클래스의 객체를 생성할 때는 가상함수 테이블 생성되지 않음), 그것을 AA클래스 포인터로 바라보면서 해제하려고 하니까

[가상함수 테이블 주소]

[_Aa] <<<< A1는 지금 이 곳을 보고 있음.

[_Bb]

 

여기서 delete -> free를 할 때 처음에 할당했던 공간 앞뒤로 넣었던 체크 값을 확인하는 과정에서

[heap 체크섬]

[가상함수 테이블 주소]

[_Aa] <<<< A1는 지금 이 곳을 보고 해제하려고 함.

[_Bb]

[heap 체크섬] 인데

해제하려는 포인터가 잘못됐다! 라는 판단을 내리고 _CrtIsValidHeapPointer라는 런타임 에러를 발생시킨 것 같습니다.

 

소멸자를 Virtual로 붙여서 해결되는 이유도 BB의 정확한 해제가 가능해서 그런 것 같고요

0

hush park님의 프로필 이미지

2024. 06. 19. 17:21

소멸자에 virtual을 안붙여서 생긴 문제였네요 해결되었습니다.. ㅠ

0

인프런 AI 인턴님의 프로필 이미지

2024. 06. 19. 16:31

안녕하세요, 인프런 AI 인턴입니다. hush park님의 질문에 대해 답변 드리겠습니다.

질문의 핵심은 virtual 키워드를 자식 클래스의 멤버 함수에 추가했을 때 발생하는 중단점 에러에 대한 이해입니다. 이는 C++의 상속과 가상 함수(virtual functions) 메커니즘에 대한 깊은 이해가 필요한 문제입니다.

virtual 키워드를 사용함으로써, 해당 함수는 런타임에 결정되는 다형성의 특성을 가집니다. 즉, 포인터나 참조를 통해 해당 객체를 다룰 때, 객체의 실제 타입에 따라서 호출되는 함수가 결정되게 됩니다.

문제에서 설명한 현상은 delete A1; 실행 후 A1이 가리키는 메모리가 해제되었음에도 A2->Info();를 통해서 접근을 시도하는데, 이는 A2가 여전히 해제된 메모리 영역을 가리키고 있기 때문에 발생하는 문제입니다. virtual 함수를 사용하면, 객체의 소멸 과정에서 가상 함수 테이블(vtable)을 참조하는 과정이 포함됩니다. 만약 메모리가 해제된 이후에 vtable을 참조하려고 하면 접근 위반 오류가 발생할 수 있습니다.

이에 관련하여 비슷한 상황에서 발생하는 메모리 해제, 가상 함수에 관한 이해를 돕는 질문과 답변이 있으니 참고하시길 바랍니다:
“안녕하세요! virtual 소멸자에 대해서 질문드려요!”에서 질문자는 상위 클래스의 소멸자에 virtual을 붙이지 않았을 때 발생하는 메모리 누수에 대해 테스트를 진행하였으며, 성능 프로파일러를 사용하여 메모리 누수 여부를 확인하는 과정을 설명합니다.

다만, 주어진 링크는 질문자님의 케이스와 정확히 일치하지 않을 수 있습니다. 그러나 가상 함수와 소멸자의 관계, 메모리 관리에 대해 학습하는 데 도움이 될 것입니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

작성자 없음

작성자 정보가 삭제된 글입니다.

질문하기