혹시나 싶어서 여기 게시판에서 검색하니 나오지 않더군요..

모르시는 분들 계실까봐 적어봅니다...

 

 

보통 잘못된 메모리 영역에 쓰기를 하는 경우(memory corruption) 오류가 즉시 발생하지 않습니다..

이런 오류를 잡기가 참으로 난감한데요..

 

그럴 때 _ASSERT(_CrtCheckMemory()); 를 많이 사용하셨을 겁니다.

 

-------------------------------------------------

_CrtCheckMemory()에 대한 사용법은.. 아실거라고 가정하고..

DCRT를 사용하기 위한 준비 작업만 간단하게 적어봅니다.

 

//stdafx.h 제일 처음에 선언

#define _CRTDBG_MAP_ALLOC   

 

//stdafx.h 제일 마지막에 선언

#include <crtdbg.h>    

// main() 제일 처음에 선언

 _CrtSetDbgFlag(
  _CRTDBG_CHECK_ALWAYS_DF
  |_CRTDBG_LEAK_CHECK_DF
  |_CRTDBG_ALLOC_MEM_DF
  |_CRTDBG_DELAY_FREE_MEM_DF
  );

-------------------------------------------------------

 

그런데 _CrtCheckMemory()를 사용해서 커럽션 발생 유무는 확인 할 수 있어도

어느 부분이 문제인지는 알 수 없습니다.

결국  _ASSERT(_CrtCheckMemory()); 를 의심되는 코드에 넣어가면서 범위를 좁히게 되는데요..

그럼에도 불구하고 문제를 해결하기 난감한 상황이 올 수 있습니다.

 

그럴 때 아래와 같은 코드를 사용하면 효험을 볼 수 있습니다.

 

_ASSERT(_CrtIsMemoryBlock(buffer, size, NULL,NULL,NULL));

 

_CrtIsMemoryBlock()는 지정된 메모리 영역이 올바른 힙 메모리인지 검증합니다.

 

스택 메모리나.. 이런 것은 안 됩니다. 힙만 됩니다.

 

그래서.. IOCP와 같은 비동기로 메모리에 쓰기 요청을 하기 전에 위와 같은 코드로 검증을 하면..

커럽션이 발생할 것인지 미리 알 수 있습니다.

 

상큼하게..

 

 void Transfer::PreRequest(BYTE* buffer, int size)
 {
    _ASSERT(_CrtIsMemoryBlock(buffer, size, NULL,NULL,NULL));

 }

 

위와 같이 전달 받은 포인터로 작업을 하는 함수의 제일 상단에 검증하는 코드를 넣어주면...

뭔가 있어 보입니다... ^^

 

------------------------------------------------------------

퇴근 시간이 조금 남아서 예제 하나 만들어 봤습니다.

진작 만들걸.. 하는 후회가 듭니다... T_T

 

#define _CRTDBG_MAP_ALLOC

 

#include <tchar.h>

#include <memory>

 

#include <crtdbg.h>

 

int _tmain(int argc, _TCHAR* argv[])

{

        _CrtSetDbgFlag(

               _CRTDBG_CHECK_ALWAYS_DF

               |_CRTDBG_LEAK_CHECK_DF

               |_CRTDBG_ALLOC_MEM_DF

               |_CRTDBG_DELAY_FREE_MEM_DF

               );

 

 

        int* p=new int[10];

        const int size=sizeof(int)*10;

 

        //p[9]까지유효하기때문에p[10]에무언가를기록하면

        //Memory Corruption이다커럽션이발생한이후에

        //_CrtCheckMemory()를실행하면false를리턴한다.

        _ASSERT(true==_CrtCheckMemory());

        p[10]=0;

        _ASSERT(false==_CrtCheckMemory());

 

        //할당한후_CrtIsMemoryBlock로영역을체크하면true를리턴

        _ASSERT(true==_CrtIsMemoryBlock((const void *)p, size, NULL, NULL, NULL));

 

        //할당된 메모리의 제일 처음이 아닌 임의의 주소를 검사하면 false 리턴

       //찾아보지는 않았지만 메모리 할당 테이블을 유지하고 있는데..

       //이 테이블에서 p+2로 탐색이 안 되서 그럴거라 추측합니다.

       //아시는 분의 제보 기다립니다.

        _ASSERT(false==_CrtIsMemoryBlock((const void *)p+2, size-2, NULL, NULL, NULL)); 

 

        //pdelete 한후에_CrtIsMemoryBlock로영역을체크하면

        //올바르지않은힙영역이기때문에false가리턴된다.

 

        delete[] p;

        _ASSERT(false==_CrtIsMemoryBlock((const void *)p, size, NULL, NULL, NULL));

 

        return 0;

}

'NativeCode > api' 카테고리의 다른 글

IpHlpApi MSDN  (0) 2010.07.04
SendARP  (0) 2010.07.03
WSAGetLastError()  (0) 2010.04.06
Sock 정보들  (0) 2010.04.04
소켓 옵션  (0) 2010.04.01
힙이나 스택에서 초기화를 안하면 뭔 값이 들어갈까?? 
마소에서 마음데로 정해 줬겠지만..ㅋㅋ
그래서 검색해봤다.

0xcccccccc : 초기화 되지 않은 지역 변수
0xcdcdcdcd : 초기화되지 않은 힙에 할당된 메모리
0xdddddddd : 힙에서 free된 메모리
0xfeeefeee : 힙에서 free된 메모리
0xfdfdfdfd : 힙에 할당된 메모리의 초가 범위(할당된 메모리의 양 끝 )
이런 비밀이 있었다.


'Programming > 이것저것' 카테고리의 다른 글

Symbol  (0) 2010.04.24
IL Code에 심볼 정보가 포함되는 이유  (0) 2010.04.24
[Design Pattern] Singleton Pattern  (2) 2010.04.16
typeid 연산자  (1) 2010.04.15
enum 문자열  (0) 2010.04.09

+ Recent posts