레이블이 Visual Studio인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Visual Studio인 게시물을 표시합니다. 모든 게시물 표시

토요일, 6월 21, 2008

Visual Studio 6.0에서 STL의 Memory Leak 해결

 

가변형의 메모리 구조를 이용하기 위해 C++의 STL을 처음 사용해 보는 과정에서

Visual Studio 6.0에서는 STL이 문제가 많다는 것을 알게 되었다.

혹자는 자신의 블로그에서 VS6.0에서 STL을 사용하는 사람은 도시락을 싸가지고 다니며 말리고 싶다고 할정도...

VS 2005 이후로 STL이 안정화 되었다고는 하나 테스트 해보지는 않았다.

결정적 이유는 이미 코드가 너무 거대해져 버린것..-_-;;

거기다 뽀대좀 내보겠다고 사용한 상용 GUI 라이브러리 부터 시작해서 XML parser에 이르기 까지

VS2005 이후 버전에 호환되지 않는다는 문제가 섣부른 버전 업그레이드를 망설이게 했다.

그렇다고 STL을 포기하자니, 중요한 알고리즘부를 몽땅 들어내야 하는 더 큰 문제가 있었다.

초기에 leak 체크를 하지 않고 좋다구나 하고 코딩한 죄다....T_T

그리하여 '어차피 코드, 인간이 만든 구조물에 해결 방법이 없는 것은 없다!' 라는 일념으로 웹을 뒤지고

이리저리 테스트를 통해 leak을 해결할 방법을 찾은 듯하다.

그래서 VS6.0에서 STL을 사용하는데 주의점을 기록해 두고자 한다.

 

1. Leak의 원인이 되는 clear() 의 오동작

STL의 메모리 해제를 위해 제공되는 함수가 clear()함수인데 이것이 제대로 기능을 하지 않는 듯하다.

여러 자료에서 새로운 instance를 생성하고 이것과 swap하는 방법을 추천하는데, vector에는 이것이

잘 동작하지만, map에는 잘 동작하지 않는다.

그리하여 찾아 낸것이 새로운 instance를 반드시 NULL로 초기화 해주고 이것과 swap을 해야 한다는

것이다.

예를 들어 vector<int> vTest과 map<int,float> mTest가 있을 때

반드시 vTest.swap(vector<int>(NULL)) 과 mTest.swap(map<int,float>(NULL,NULL)) 과 같은식으로

메모리를 해제해 주어야 leak이 발생하지 않는다.

2. Hash map의 iterator

Userdefined type의 object를 map에서 사용할 때에는 iterator를 사용하기 위해서는 instance간에

크기 비교가 가능하도록 method를 만들어 주어야 한다.

예를 들어 map<CTransKey,float>에서 CTransKey에는 operator<가 반드시 정의되어야 한다.

class CTransKey 
{
public:
    CTransKey();
    CTransKey(CState& s0,CAction& a0,CState& s1);
    CTransKey(const char* s0, const char* a0,const char* s1);
    virtual ~CTransKey();

    bool operator==(const CTransKey& k);
    friend bool operator< (const CTransKey& k1,const CTransKey& k2);

    CState CurState;
    CAction CurAction;
    CState NextState;

};

bool operator< (const CTransKey& k1,const CTransKey& k2);

목요일, 4월 03, 2008

Matlab에서 만든 function을 C library로 Visual Studio 6.0에서 이용하기 기초 테스트

참고 사이트

http://www.mathworks.com/support/solutions/data/1-2QTWCE.html?solution=1-2QTWCE

http://www.nbs.ntu.edu.sg/userguide/MatLab/MatLab6/toolbox/mathlib/cmathug/cmathug.html

http://www.fsa.ucl.ac.be/help/helpdesk.html


  1. 우선 Matlab의 Matlab Component Runtime Library를 인스톨 합니다.

    MATLAB의 \toolbox\compiler\deploy\win32 폴더의 MCRInstaller를 실행하여 설치합니다.


  2. Matlab에서 원하는 Function을 작성합니다.

    예를 들어 Inverse.m 을 다음과 같이 작성합니다.


    function y=inverse(x)

    y=inv(x);


  3. 먼저 compiler를 setting합니다.

    Matlab command창에서

    mbuild -setup을 실행하면 시스템에 설치된 컴파일러를 찾아 선택하게 됩니다.


  4. Matlab에서 해당 function을 컴파일 합니다.

    Matlab command 창에서

    mcc -B csharedlib:inverselib inverse.m

    을 실행하면 inverselib.h inverselib.c inverselib.lib…. 등등의 파일을 생성합니다.



  5. Visual studio에서 테스트 프로젝트를 하나 만듭니다.

    이 프로젝트 폴더로 아까 matlab이 생성한 파일들을 모두 카피합니다.

    그리고 이 프로젝트가 matlab library를 사용할 수 있게 환경을 setting해 줍니다.

    Tools->Options->Directories 의

    include 와 library 의 path에 각각

    C:\MATLAB7\extern\include

    C:\MATLAB7\extern\lib\win32\microsoft\msvc60

    를 추가해 줍니다.

    그리고 Project->Settings->Link의 Object/library modules:에

    mclmcrrt.lib inverselib.lib를 지정해 줍니다.


  6. View의 Header입니다.

    만든 라이브러리를 사용하기 위해 헤더 inverselib.h를 include 해 주고,

    행렬의 입력, 출력을 확인하기 위해 mxArray 포인터 타입의 변수 2개를 선언합니다.


    #include "inverselib.h"


    class CMatlabLibView : public CView

    {

    …...

    mxArray *pX;

    mxArray *pY;

    …..

    };


  7. View class의 OnCreate 함수

    라이브러리의 초기화를 해 줍니다.


    if( !mclInitializeApplication(NULL,0) )

    {

    AfxMessageBox("Could not initialize the application.");

    exit(1);

    }


    if (!inverselibInitialize())

    {

    AfxMessageBox("Could not initialize the library.");

    exit(1);

    }


  8. View class의 OnDraw함수


    2X2 행렬 하나를 만들고 inverse를 구해 출력해 봅시다.


    int rows=2;

    int cols=2;


    static double data[] = { 1, 2, 3, 4 };

    double *start;


    pX = mxCreateDoubleMatrix(rows,cols,mxREAL);

    start = (double *)mxGetPr(pX);

    memcpy(start, data, rows * cols * sizeof(double) );


    pY=NULL; <---- 반드시 NULL로 지정해 주어야 합니다.

    mlfInverse(1,&pY,pX); <---- matlab에서 생성한 library의 함수 입니다.


    double *x,*y;


    x=(double*)mxGetPr(pX);

    y=(double*)mxGetPr(pY);


    for (int i=0;i<rows;i++)

    {

    for (int j=0;j<cols;j++)

    {

    double xx,yy;

    xx=*(x+cols*i+j);

    yy=*(y+cols*i+j);

    CString str;

    str.Format("%1.3f",xx);

    pDC->TextOut(50*j,20*i,str);

    str.Format("%1.3f",yy);

    pDC->TextOut(200+50*j,20*i,str);

    }

    }


  9. View class의 OnDestroy 함수

    끝나면 정리는 항상 확실히


    mxDestroyArray(pX);

    mxDestroyArray(pY);

    inverselibTerminate();

    mclTerminateApplication();



목요일, 3월 13, 2008

Visual studio에서 classview가 제대로 동작하지 않을 때

연구실의 종찬이나 정연형 처럼 fileview를 보며 코딩하는 사람들은 상관 없지만,

나처럼 classview를 주로 보면서 코딩하는 사람들은

가끔 이 view가 제대로 동작하지 않을때 대략 난감해진다.

이 때 해결하는 방법은

프로젝트를 닫고 *.APS, *.NCB, *.OPT, *.CLW, *.PLG

파일들을 모두 지우고 다시 프로젝트를 열면 된다.

단, 이때, classview를 나름대로 폴더 별로 정리해 놓은 경우 이 분류는 모두 사라지므로

다시 정리해 줘야 한다.