C++ 잘못된 메모리 참조에 대한 유효성 검사

2021. 11. 16. 11:23개발/C++

iocp를 다루는 중 자꾸 댕글링포인터가 발생해서 서버가 죽는 현상이 나타났다.

해당 포인터를 다른 사람이 만들었다는 것이 문제다.

내가 제어할 수가 없는 상황이라서 난감한 상황

 

포인터가 잘못된 메모리를 가르키면 어떻게 해야할까?

 

//main
#include <iostream>
#include "Ptr.h"

int main()
{
    std::cout << "Hello World!\n";
    
    Ptr* ptr = (Ptr*)malloc(sizeof(Ptr));
    ptr->SetStr("qwer");
    printf("%s\n",ptr->GetStr());
    
    free(ptr);
    
    printf("%s\n",ptr->GetStr());
}

//Ptr.h
#include <corecrt_memory.h>
class Ptr
{
public:
	Ptr();
	~Ptr();

private:
	char str[32] = "adcd";

public:
	void SetStr(const char* param) { memset(str, 0, 32); memcpy(str, param, 32); }
	char* GetStr() { return str; }
};
//결과
Hello World!
qwer
硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼硼;

보다시피 쓰레기값이 들어가게 된다.

유효성 검사를 하려면 어떻게 해야할까?

 

 

기본적으로 포인터에 NULL처리를 미리 해줘서 판단하면 된다.

 

//main
#include <iostream>
#include "Ptr.h"

int main()
{
    std::cout << "Hello World!\n";
    
    Ptr* ptr = (Ptr*)malloc(sizeof(Ptr));
    ptr->SetStr("qwer");
    printf("%s\n",ptr->GetStr());
    
    free(ptr);
    ptr = NULL;
    
    if(ptr != NULL)
    	printf("%s\n",ptr->GetStr());
}

//Ptr.h
#include <corecrt_memory.h>
class Ptr
{
public:
	Ptr();
	~Ptr();

private:
	char str[32] = "adcd";

public:
	void SetStr(const char* param) { memset(str, 0, 32); memcpy(str, param, 32); }
	char* GetStr() { return str; }
};
//결과
Hello World!
qwer

 

이런것들이 잘되어있으면 상관없지만...

문제는 NULL처리가 안되어있는 댕글링 포인터가 날아온다는 것이다.

여러 방법을 생각하던 중..

 

 

 

 

고심끝에 금단의 방법을 사용했다.

//main
#include <iostream>
#include "Ptr.h"

int main()
{
    std::cout << "Hello World!\n";
    
    Ptr* ptr = (Ptr*)malloc(sizeof(Ptr));
    ptr->SetStr("qwer");
    printf("%s\n",ptr->GetStr());
    
    free(ptr);
    
    if(ptr->IsAlive())
    	printf("%s\n",ptr->GetStr());
}

//Ptr.h
#include <corecrt_memory.h>
#define  CHECK_ALIVE	0x0F0F0F0F

class Ptr
{
public:
	Ptr();
	~Ptr();

private:
	char str[32] = "adcd";
	unsigned long isAlive;

public:
	void SetStr(const char* param) { memset(str, 0, 32); memcpy(str, param, 32); isAlive = CHECK_ALIVE;}
	char* GetStr() { return str; }
	bool IsAlive() { return isAlive == CHECK_ALIVE; }
};

 

그냥 클래스를 초기화할때 아예 유효성키를 박아서 살아있는지 확인하는 방법이다.

 

실제로는 iocp에서 형변환등 여러 복잡한 과정이 있지만, 회사코드를 쓸수는 없으니 그냥 개념만 간단하게 해봤다.