프로그래밍 2022. 5. 18. 09:37
728x90

 

Windows가 ngg_MapTool.exe에서 중단점을 트리거했습니다.

힙이 손상되어 ngg_MapTool.exe 또는 여기서 로드한 DLL에 버그가 있을 수도 있습니다.

ngg_MapTool.exe에 포커스가 있을 때 사용자가 F12 키를 눌렀기 때문일 수도 있습니다.

자세한 진단 정보는 [출력] 창을 참조하십시오.

HEAP[ngg_MapTool.exe]: HEAP: Free Heap block 14B7C7C8 modified at 14B7D2AC after it was freed
Windows가 ngg_MapTool.exe에서 중단점을 트리거했습니다.

 

 

 

힙손상 버그

 

며칠동안, 이 버그의 원인을 찾느라,

날려버린 시간들...

 

하아,,,

 

맵툴에서 위젯(풀 군락 같은것)을 놓고, 삭제하는 과정에서 발생

 

지금껏, 오랜기간 문제없이 사용하던 부분에서 갑자기 발생

 

Why?

 

위젯의 삭제 코드를 살펴보았지만, 코드자체로는 별다른 이상을 발견못함

 

위젯에 포함, 연결되어 있는, 수많은 new , delete, 초기화, 사용, 모두 체크해 보았지만, 괜찮았음

 

 

 

 

발생되는 힙손상 위치는 계속 바뀌고,

 

도대체 원인이 뭘까, 머리를 쥐어뜯으며 고민

 

Why?

 

Why?

 

 

 

 

 

인터넷을 뒤져 보니,

발생 원인을 대충 정리해 보면,

 

1. dll 에서 생성한 메모리를 exe 에서 해제할때,

exe 에서 생성한 메모리를 dll 에서 해제할때

메모리 깨짐

 

2. new 로 할당한 메모리의 범위를 벗어난 

초기화나, memcpy 사용했을때

즉, 메모리 오버런

 

3. 메모리 오버런 상태에서, 그 메모리를 해제했을때

 

요약하면,

new 로 할당한 힙메모리 영역을 잘못 건드렸고,

이를 delete 할때 힙손상이 일어난다는것

 

일단, dll 프로젝트를 사용하지 않으니 패스

외부 dll 도 특별히 짚이는 부분은 없고,

 

아무리 살펴봐도, 메모리 사용을 잘못하는 부분이 없다는것,

나의 경우, 멤버변수의 초기화를 잘하는 편이고,

생성, 사용, 코드 곳곳에 에러체크코드를 추가해 놓았다.

 

 

어쩔수없이, 

소거법을 진행

 

메모리릭이 나더라도

위젯의 멤버변수들을 delete 하는 것을 막고,

test 

-> 여전히 발생

 

위젯에서 bsp tree list 생성을 막고,

임시코드를 써서 test

-> 여전히 발생

 

위젯 멤버변수의 문제가 아니라,

위젯자체를 위젯매니져에서 delete 할때

문제가 생기는 것은 확실한데,

 

아무리 찾아보아도 

위젯을 지울때 왜 문제가 생기는지를 알수가 없었다.

 

 

그렇게,

 

머리를 쥐어 뜯다가

 

바람도 쐴겸, 동네를 한바퀴 돌고 와서, 다시 책상에 앉았다.

 

그리고,

 

침착하게,

 

힙이 손상되어 또는 여기서 로드한 DLL에 버그가 있을 수도 있습니다

문구로, 다시 인터넷을 검색

(벌써 여러번 살펴보았지만,)

 

인터넷 포스팅들이 다시 주르륵 검색되고,

 

뭔가 놓친 힌트가 있지 않을까 해서

 

그중 제일 첫번째 포스트에 들어가서 읽어보았는데,

(이미 여러번 읽었던 포스트를 다시 읽었다)

 

이 포스트는 dll 에서 사용한 메모리를 exe 에서 해제할때, 힙손상이 생긴다는 포스팅 이었다

 

 

으음,,,

나는 dll 프로젝트를 사용을 안하는데,

위젯코드가 들어있는 엔진은 lib 형식이고,

 

잠시 생각을 해보다가,

 

문득,

 

맵툴에서 위젯을 추가하는 코드는, 맵툴프로젝트(exe)에서 사용되고 있고,

맵툴에서 위젯을 지울때는, flag 를 하나만 주어서,

실제, 삭제는 engine.lib 프로젝트에서 실행해 주고 있다는 것이 

확 와닿았다

 

엇, 그러고보니, 

한두달 전에, 맵툴 코드를 좀 정리하면서,

위젯 지우는 코드를 lib 안으로 옮겼었지 

 

그렇다,

 

와닿았다

 

이미 알고 있는 부분이었으나, dll 이 아니었기 때문에, 

신경을 안쓰고 있었는데,

 

dll <-> exe 에 문제가 생길수 있다면

lib <-> exe 에도 문제가 생길수 있는?

라는데에 생각이 닿은것이다

 

 

엔진 프로젝트 lib 에서 위젯을 삭제하는 코드

외부로부터 flag 를 받아서, lib 안에서 delete 가 호출된다 

 

맵툴 프로젝트 exe 에서, 위젯을 추가하는 부분

 

 

엔진 내부에서 delete 하던 부분을, 맵툴 프로젝트로 코드를 옮겨서 실행

그리고

test

 

어라,,,

 

해결!

 

즉, 맵툴 프로젝트안에서

추가와 삭제를 모두 실행하니까 문제가 없어졌다

 

즉,

new , delete 사용 함수를 모두 맵툴 프로젝트 안에서 호출

new , delete 사용 함수를 모두 같은 프로젝트 안에서 호출해야 한다는 것!

 

힙손상의 원인은

new 사용 함수를 맵툴 프로젝트에서 호출

delete 사용 함수를 엔진 라이브러리 에서 호출 했을때

 

 

 

 

와아,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

 

힙손상은 dll, exe 

이전부터 이렇게 기억하고 있었고,

지금 검색해 보아도, 보통 dll 이 따라 붙어서,

 

lib, exe 에서 문제가 될수있다는 것을, 아예 생각도 하지않고 있었다

아니, 어쩌면, 이전에 알던 부분이었는데,

오랫동안 별 문제없이 사용을 해서,

까먹었었나

 

기억을 더듬어보면, 이전에 다른 게임 프로젝트를 진행할때에도,

이런 문제가 있었던것 같기도 하고, 가물가물 하기는 한데,

 

어쨋든,

 

공식처럼 기억하고 있던, 일반화의 오류 덕분에

아주 고생을 했다.

 

인터넷에서,

좀더 자료를 찾아보아도,

 

힙손상 관련해서는,

 

보통 항상 dll 이 끼어져 있다,

 

아니, 왜 lib 는 빠져있는 것일까

 

분명, 문제가 있는데,

 

하 내참,

 

짜증나네,

 

 

그러고보니,

나처럼 여러개의 lib 프로젝트를 사용하는 경우,

각각의 lib 마다 힙영역이 다른 것일까

 

나는 그럴 것이라 생각한다

이것을 증명할수 있는 방법, 코드 같은 것이 있을까

 

그렇다면, 각각의 lib 안에서 new, delete 를 사용하는 

객체나 함수들은 아주 세심하게 관리를 해주어야 하는것이 아닌가?

 

음? 아니,

 

나는 그렇게 세심하게 관리안하고도 지금까지 잘 사용했는데,

,,,,,

별 문제없이,

 

차분히 생각해보면,

core, engine 등의 lib 에서도 수많은 new, delete 사용 함수들이 있지만,

 

보통, 실제 사용은 

실행 프로젝트에서 new, delete 사용 함수를 호출하기 때문에,

실행 프로젝트의 힙영역을 사용하는 것이 되겠다

 

음 그러면,

 

lib 에 있는

어느 클래스 소멸자에, 멤버변수의 delete 가 포함된 경우라면 어떻게 될까?

 

자칫 골치 아플것 같긴 한데,

 

생각해보니,

 

으음~

 

문제없다

 

이 클래스가 하나의 프로젝트 안에서 new, delete 가 잘 되었다면,

그의 멤버변수도 같은 과정을 거치게되니, 걱정할 필요가 없다

 

 

최종 요약해 보자

 

lib 안의

WidgetNew() - 함수 내부에 new 코드 포함

WidgetDelete() - 함수 내부에 delete 코드 포함

 

 

실행 프로젝트에서 사용할때는

 

MapTool_Frame() 안에서

위젯 추가할때 WidgetNew() 호출

위젯 삭제할때 WidgetDelete() 호출

 

lib 안의

할당과 해제 함수를, 실행 프로젝트에서만 사용해 주자

 

 

728x90
posted by BK dddDang
: