코딩할때 가장 기본이 되는 유용한 기능중 한가지가 바로 배열이라고 생각합니다.

 

 

배열은 동적 메모리 할당(dynamic memory allocation)정적 할당(static memory allocation)으로 선언할수있습니다.

 

 

또한 정적할당에서도 메모리가 할당이 되는곳이 선언방법에 따라 힙(heap) 영역과 스택(stack) 영역으로 나뉠수 있습니다.

 

 

간단히 이야기 해서 스택은 용량이 1메가바이트 (1MB = 1,000 KB = 1000,000 byte) 정도로 한정이 되어있다고 합니다.

 

 

그래서 지역번수를 선언할때 메모리 할당, 즉 배열 선언을 할때 정적배열의 크기가 너무 커버리면 스택 영역에 있어야 할 지역변수의 공간이 이웃한 다른 영역을 침범하게 되서 메모리 접근 오류가 발생할 수 있습니다.

 

 

결론은 간단히 이야기 해서 전역으로 정적 배열을 선언해버리면, 데이터 영역, 즉 힙 영역으로 메모리가 할당이 되어서 오류가 뜨지않고 사용을 할 수 있습니다.

 

 

오늘 작업하다가 지역함수 내에서 정적 메모리 할당을 했는데, 계속 오류가 뜨길래 찾아보고 찾아보다 그 해결책을 찾은거라 혹시나 해서 다른분들께도 도움이 되지않을까 해서 글 적어봅니다.

 

 

typedef double_double3_[3];

_double3_arrA[640*480];

_double3_arrB[640*480];

_double3_arrC[512*424];

 

 

위와 같이 정적 배열을 생성했는데, 계속 오류가 떠서, 전역으로 옮겨 줬더니 문제 없이 작동 되네요.

 

 

조금 더 자세한, 그리고 디테일한 설명을 원하시면 아래 참조 블로그를 들어가셔서 보시면 더욱 더 이해하시기 편하리라 생각합니다.

 

 

참조:

http://egloos.zum.com/slaveofcod/v/320270

http://inhack.org/wordpress/?p=2932

 

 

Posted by Tommy™
,

이번에 윈도우 8.1 에서 윈도우 10 으로 업그레이드를 하게 되었는데, 문제없이 잘 동작하던 프로그램이 갑자기 말썽을 일으켰다. 

 

주 모니터에서는 잘 시뮬레이팅 되는 프로그램이 보조 모니터에서는 계속 이상한 결과를 계속 보여줬는데, 결과적으로 마우스 좌표가 이상하게 들어와서 계속 시뮬레이팅이 이상하게 되었던것이었다.

 

이리저리 알아 본 결과,

 

윈도우 10에 있는 "디스플레이 사용자 지정" 항목에서 "텍스트, 앱 및 다른 항목의 크기를 변경합니다" 부분이 많은 영향을 미치는거 같다.

 

 

주 모니터와 보조 모니터의 확대 % 를 같게 해줘야 같은 결과를 내는데, 두개의 확대 %가 달라서 마우스 좌표값이 다르게 입력 되었던 것이었다.

 

보조 모니터의 크기가 커서 확대를 더 많이 했더니 이러한 예상치 못한 오류를 도출하게 되었는데, 조심해야겠다.

 

혹시나 하는 마음에 다른분들도 문제가 발생 할 수도 있어서 알려드리고자 블로깅을 했습니다.

 

 

 

 

모니터 해상도, 보조 모니터 포함 해상도 및 디스플레이 정보 관련 코드

 

int mx = GetSystemMetrics(SM_CXSCREEN);    //Main monitor resolution - width

int my = GetSystemMetrics(SM_CYSCREEN);    //Main monitor resolution - height

int wx = GetSystemMetrics(SM_CXVIRTUALSCREEN);    //Whole resolution - main + sub monitor - width

int wy = GetSystemMetrics(SM_CYVIRTUALSCREEN);    //Whole resolution - main + sub monitor - height

int sx = wx - mx;    //Sub monitor resolution - width

int sy = wy - my;    //Sub monitor resolution - height

int MonitorCount = GetSystemMetrics(SM_CMONITORS);    //Monitor count

 

 

모니터 정보

 

HMONITOR hMon = MonitorFromWindow(GetSafeHwnd(), MONITOR_DEFAULTTONEAREST);

MONITORINFO monInfo;

ZeroMemory(&monInfo, sizeof(MONITORINFO));

monInfo.cbSize = sizeof(MONITORINFO);

GetMonitorInfo(hMon, &monInfo);

 

 

 

Posted by Tommy™
,

프로그램을 만들다보면 이런저런 예외처리나 에러가 날법한 곳에 메세지박스나 콘솔창에 디버그 결과를 띄울경우가 많다. 그러다 assert 매크로를 알게 되었는데, 너무나도 유용하면서 편하게 디버깅을 할수 있는 방법이다. 직접 블로깅 하려다가, 어떤 분께서 아주 정리를 깔끔하게 해놓으셔서 긁어오게 되었다. 출처 및 주소는 밑에..

 

 

" assert의 비법들 "

 

1. assert의 기본

  - assert 매크로 : 코드 상의 어떠한 가정을 철저하게 점검하기 위한 간단하면서도 부담 없는 방법

  - 항상 TRUE가 되어야 하는 조건식을 넣는다. 조건이 FALSE로 평가되면 assert는 문제가 생겼음을 알리는 대화상자를 띄운다.

  - 프로그램을 방어적으로 만들어 준다.

  - 디버그 빌드에서는 수행하지만 릴리즈 빌드에서는 assert 매크로가 컴파일되지 않는다. 그러므로 assert 안에서 프로그램의 상태를 변화시켜서는 안된다.

  #include <assert.h>

  void VectorNormalize( Vec* src, Vec* dst ) {

    assert( src != 0 );

    assert( dst != 0 );

  }

 

2. assert 비법_1) 더 많은 정보를 집어넣는다.

  - assert의 조건식에 더 많은 정보를 집어 넣는다.

  #include <assert.h>

  void VectorNormalize( Vec* src, Vec* dst ) {

    assert( src != 0 && "VectorNormalize::src vector pointer is NULL " );

    assert( dst != 0 && "VectorNormalize::dst vector pointer is NULL " );

  }

 

3. assert 비법_2) 좀더 많은 정보를 집어넣는다.

  - 프로그램의 실행이 도달하지 말아야 할 곳에 도달하는 상황을 감지하기 위해서 assert(0)를 사용하는 경우도 있다. 항상 실패.

  - 부정 연산자 사용

  - assert( !"VectorNormalize:: The code should never get here" );

 

4. assert 비법_3) 좀더 편하게

  - 두 개의 인자들을 받는데, 첫번째 것은 실제로 평가될 조건식이고 두번째 것은 디버깅 정보를 담는 문자열이다.

  - #define Assert(a,b) assert( a && b )

  - Assert( src != 0, "VectorNormalize::src vector pointer is NULL " );

    Assert( 0, "VectorNormalize:: The code should never get here" );

 

5. assert 비법_4) 커스텀 assert 만들기

  - assert보다 더 많은 기능을 가진 독자적인 검사 매크로를 만들 수 있다.

  - 디버거 하에서 조건이 실패ㅏㄹ 경우 소스파일 안의 assert 문이 아니라 assert.c 파일 안에서의 assert 문으로 들어가게 되는 경우 소스파일로 직접 들어가게 만들때 사용된다.

  #if defined(_DEBUG)

    extern bool CustomAssertFunction( bool, char*, int, char* );

  #define Assert( exp, description ) \

    if( CustomAssertFunction( (int)(exp), description, _LINE_, _FILE_) ) \

    { _asm { int 3 } }

  #else

  #define Assert( exp, description )

  #endif

 

6. assert 비법_5) 이것도 중요

  - 커스텀 assert 매크로를 만드는 경우에는 assert 대화상자에 다음부터 항상 무시 옵션을 추가하는 것이 좋다

  - 특정 assert 문에 대해서는 조건이 실패해도 대화상자를 표시하지 않고 무조건 넘어갈 수 있도록 하는 것이다.

  #if defined(_DEBUG)

    extern bool CustomAssertFunction( bool, char*, int, char* );

  #define Assert( exp, description ) \

    { static bool ignoreAlways = false; \

      if( !ignoreAlways ) { \

        if( CustomAssertFunction( (int)(exp), description, _LINE_, _FILE_) ) \

        { _asm { int 3 } }

      } \

    }

  #else

  #define Assert( exp, description )

  #endif

 

7. assert 비법_6) 초고수만 볼 것

  - VectorNormalize를 호출하는 곳이 많다면 VectorNormalize 안의 assert 문은 프로그램을 디버거에 붙여서 실행하지 않는 한 큰 도움이 되지 못한다.

  - assert 대화상자 안에 스택 정보를 표시하면 된다.

 

8. assert 비법_7) 좀 더 쉽게 복사해서 붙여 넣기

  - 스택 정보를 좀 더 쉽게 보존/저장할 수 있는 방법이 필요

  - 윈도우즈 환경에서의 한 가지 해결책은 클립보드를 이용하는 것

  - assert 대화상자에 작은 버튼을 하나 만든 다음 그 버튼을 클릭할 때 스택 정보가 클립보드에 복사되도록 하면 누구라도 쉽게 클립보드의 내용을 버그 리포트나 전자 우편에 붙여 넣어서 프로그래머에게 보낼 수 있다.

  - 임의의 문자열을 클립보드에 복사하는 윈도우즈 전용 코드

  if( OpenClipboard( NULL ) )

  {

    HGLOBAL hMem;

    char szAssert[256];

    char *pMem;

 

    sprintf( szAssert, "Put assert info here" );

    hMem = GloabalAlloc( GHND | GMEM_DDESHARE, strlen( szAssert ) + 1 );

 

    if( hMem)

    {

      pMem = (char*)GlobalLock(hMem);

      strcpy( pMem, szAssert );

      GlobalUnLock( hMem );

      EmptyClipboard();

      SetClipboardData( CF_TEXT, hMem );

    }

   

    CloseClipboard();

  }

Posted by Tommy™
,

Map

 

map<key, value>   -> key에는 정렬될 값, value에는 필요한 값 (Key값을 기준으로 함께 쌍으로 저장 및 정렬됨)

 

중복된 키값을 허용 X

 

map 정렬방식

 

map<int, string, string.less<int>>    -> map의 오름차순 (그냥 map<key, value> 사용시 오름차순)

map<int, string, string.greater<int>>  -> map의 내림차순

 

 

map 추가방식

 

map<int, string> strMap;

strMap.insert( make_pair( 5, "Rjwu") );

strMap.insert( make_pair<int , string> (5, "RJwu")  );

 

삭제방식

 

strMap.erase(1);          키값 1의 Pair 가 사라짐

 

검색방식( 반환타입은 iterator)

 

map<int, string, string.greater<int>> :: iterator    iter;

iter = strMap.find(7);

 

cout << iter->first << "\t" << iter->second << endl;          //first 는 키값, second 는 데이터

 

 

multiMap

 

map과 달리

strMap[5] = "기륜"; 이런방식의 키값과 데이터 추가가 안된다.

또한 multiMap은 map 과 달리 중복된 키값을 허용한다. map 은 중복된 키값이 들어오면 나중에 들어온 pair 가 먼저것을 밀어냄

 

multimap 은 중복된 키값에 대하여 find로 검색시 먼저 들어온 데이터를 우선시한다.

multimap 은 중복된 키값에 대하여 erase 로 삭제 시 해당 키값에 해당하는 Pair 를 모두 삭제한다.

 

 

Include header

 

#include <map>

 

<map>만 추가해줘도 map, multimap 둘다 사용이 가능

 

#include <functional>

 

오름차순, 내림차순 정렬시, std::greater<key>, std::less<key> 를 사용하기 위한 헤더파일

 

 

http://stackoverflow.com/questions/16567699/stdgreater-not-defined-in-msvc2012

 

 

 

 

 

위의 블로그를 참고 했습니다.  (몇몇 필요한 내용은 추가 및 수정)

 

 

실제 사용 예 및 소스코드

 

Kinect의 depth값을 깊이 단위로 내림차순 정렬을 해야하는 경우가 발생했다.

 

처음에 map을 사용하셨지만, 치명적인 문제점이 key값이 중복이 안된다는 점!

 

depth 값이 중첩이 되는 값들은 저장이 안되고 날아가버리는 치명적인 문제가 발생했다.

 

하지만 multimap중복 ket값이 사용 가능하다.

 

그래서 map의 key 부분에 depth 값을, value값에 만든 구조체를 삽입하여 정렬했다.

 

 

//내림차순 정렬

multimap<float, RGBD, greater<float>> m_mapRGBD;

 

for( int h = 0 ; h < KINECT_RGBD_HEIGHT_MAX ; h ++ )
{
  for( int w = 0 ; w < KINECT_RGBD_WIDTH_MAX ; w ++ )
  {

    m_mapRGBD.insert( make_pair( rgbd.z, rgbd ) ) ;

  }

}

 

 

따라서 결과적으로 m_mapRGBD안에 depth값을 기준으로 자동 내림차순 정렬이 되어 문제를 해결하였다.

 


 

Posted by Tommy™
,

 

 

 

 

현재 진행중에 있는 프로젝트에서 CString -> wchar_t 으로 변환하여 스트링을 복사해야하는 상황을 맞이하게 되었다.

 

이리저리 찾아보다가, 한 블로그에서 그 실마리를 찾았는데,

 

참조(네이버블로그) : http://blog.naver.com/skywood1?Redirect=Log&logNo=100129022023

 

바로 위에 링크를 건 블로그에서 그 해답을 찾을 수 있었다.

 

 

 

 

size_t mbstowcs(

wchar_t *wcstr,        //Output

const char *mbstr,    //Input

size_t Count            //Size

);

 

해답은 바로 이 함수인데, 멀티바이트 스트링(MBS)을 와이드 캐릭터 스트링(WCS)으로 변경해주는 함수이다.

 

참조(MSDN) : http://msdn.microsoft.com/ko-kr/library/k1f9b8cy.aspx

 

 

 

 

하지만 나는 Cstring 에서 wchar_t로 변경해야하기때문에, 한번 더 변환을 해줘야했다.

 

CString str="test";
char *text = (char*)((LPCSTR)str); 

 

 

 

 

따라서 결과적으로 CString -> char* -> wchar_t총 3번변경을 해줌으로써 문제를 해결할 수 있었다.

 

CString str="Hand/Finger Tracking and Gesture Recognition";
wchar_t wstr[256] = {};

int nLen = str.GetLength()+1;

mbstowcs(wstr,(char*)((LPCSTR)str), nLen);

 

 

 

 

Posted by Tommy™
,