메모리 오염이 발생한 소스
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 |