본문 바로가기
메모리관리(스마트포인터...)

ReferenceCounting(스마트포인에 전..)

by kcj3054 2022. 3. 31.

메모리 오염이 발생한 소스

class Wraight
{
public:
    int _hp = 100;
    int _posX = 0;
    int _posY = 0;
};

class Missile
{
public:
    void SetTarget(Wraight* target)
    {
        _target = target;
    }

    void Update()
    {
        int posX = _target->_posX;
        int posY = _target->_posY;
    }
public:
    Wraight* _target = nullptr;    
};

int main()
{
    Wraight* wraight = new Wraight();
    Missile* missile = new Missile();

    missile->SetTarget(wraight);

    //미사일 맞기전에 레이스가 피격당함 
    wraight->_hp = 0;
    delete wraight; //여기서 문제가 발생
    while (true)
    {
        if (missile)
        {
            missile->Update();
        }
    }

    delete missile;
}
  • 위의 소스에서 미사일 맞기 전에 레이스가 사라져서 delte를 하게되면 문제가 발생한다
    • 아직 미사일 내부에 wraight 메모리를 가지고 있는 상태이다..
    • 그래서 미사일 내부에서 Update()가 실행되면 좌표에 쓰레기 값으로 Update가 된다..
  • 크래쉬가 나지않고 메모리 오염이 발생한 것은 더 위험한 일이다...

메모리 오염을 막기 위한 ReferenceCounting 방법! (싱글 스레드에서는 가능)...

RefCountable소스

#pragma once
class RefCountable
{
public:
    RefCountable() : _refCount(1) {}
    virtual ~RefCountable() {}

    int32 GetRefCount() { return _refCount; }

    int AddRef() { return _refCount++; }
    int32 ReleaseRef()
    {
        --_refCount;
        if (_refCount == 0)
        {
            delete this;
        }
        return _refCount;
    }
protected:
    int32 _refCount;
};
  • 위에서 일단 멀티스레드 환경에서는 int32로 count를 관리하는 것도 문제!

Main 소스

class Wraight : public RefCounting
{
public:
    Wraight() {}
public:
    int _hp = 100;
    int _posX = 0;
    int _posY = 0;
};

class Missile : public RefCounting
{
public:
    void SetTarget(Wraight* target)
    {
        _target = target;
        target->AddRef();
    }

    void Update()
    {
        int posX = _target->_posX;
        int posY = _target->_posY;

        if (_target->_hp == 0)
        {
            _target->ReleaseRef();
            _target = nullptr;
            return  true;
        }
    }
public:
    Wraight* _target = nullptr;    
};
  • 위에서 AddRef()를 하기전 다른 스레드가 먼저 와서 ReleaseRef()를 한 후 nullptr로 밀어버린다면?.. 공유메모리를 동시에 사용한 문제가 발생한다.. 이러한 것을 막기위해서 무조건 스마트포인터를 사용하자..

커스텀 스마트포인터.

  • 스마트포인터를 하면 값을 복사할 때 RefCounting이 1이 증가되어서 일단 없어지지 않는 다는 것을 보장 받아서 메모리 오염 문제를 완전하게 해결할 수 있다.

  • 루키스님의 서버강의를 학습한 후 작성하였습니다. .

'메모리관리(스마트포인터...)' 카테고리의 다른 글

stompAllocator, 가상메모리  (0) 2022.04.10
stompAllocator  (0) 2022.04.07
Allocator  (0) 2022.04.07
스마트포인터 (weak_ptr, unique_ptr, share_ptr)  (0) 2022.04.07