ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Visual C++ 6.0 -> Visual Studio 2010 변환
    Programming/VC++.NET 2014. 4. 15. 09:54
    출처: http://swdeveloper.egloos.com/2769838

    "Visual C++ 6.0 -> Visual Studio 2010 업그레이드시 주의 사항"
    Visual C++ 6.0 -> Visual Studio 2010 업그레이드시 주의 사항 [개발] MFC

    1. 작업 계획 세우기

    변환작업은 생각보다 만만한 작업이 아닙니다. 
    물론 소스가 몇줄 안된다면 아무 상관없겠지만 (그렇다면 새로 짜는게 낳을지도..ㅋ)
    보통 툴 업그레이드를 생각하고, 소스를 그대로 가져갈 계획이라면
    이미 그동안 6.0으로 작업했던 소스량은 엄청날 것입니다.

    당연히 계획수립은 이루어져야 합니다.
    담당자가 프로젝트를 변환 하면, 
    나머지 팀원들이 소스 변환 작업은 언제까지 할 것이며,
    그 도중에 급한 요구사항은 어떻게 처리 할 것인지..
    툴 업그레이드가 완료되면, 릴리즈 테스트는 어떻게 할 것인지 등등...

    하지만, 이런 계획이 제대로만 세워진다면
    그다음의 작업 진행은 일사천리로 이루어질 것입니다.
     

    2. 프로젝트 변환


    6.0 은 워크스페이스 파일(.dsw) 및 프로젝트 파일(.dsp)로 구성되어 있습니다.
    2010 에서는 솔루션 파일(.sin) 및 프로젝트 파일(.vcxproj)로 구성되어 있구요.

    Visual Studio 2010에서 Visual C++6.0 워크스페이스 파일을 오픈하게되면,
    변환과정을 거치게 됩니다. 우선은 그냥 OK만 계속 누르면 알아서 변환해줍니다.

    단 소스세이프를 사용했을때, 소스세이프에 제대로 연결하지 못할수도 있습니다.
    물론 Visual Studio 2010에서 소스세이프 연결 메뉴가 존재하기 때문에
    그것을 사용해도 무방하지만, 소스세이프 구조를 이상하게 사용하시는 분들은
    그것 마저도 안될 수 있습니다.  그때는 새로 생성된 sin 파일고 vcxproj 파일을 메모장에서 
    열어서 수동으로 소스세이프 연결을 진행하면 됩니다.


    3. 컴파일 에러 

    프로젝트 변환 후 컴파일을 시도 하게 되면 반드시 직면할 수 밖에 없는 문제입니다.
    문법 및 사용 함수의 프로토타입 변경등으로 컴파일 에러가 발생합니다.
    하지만, 툴에서 비교적 자세히 에러메시지를 보여주기 때문에 그리 문제될 점은 없습니다.

    a. C++ 
    문법에 관련된 오류

        - For Loop 에서 선언된 지역변수는 Loop 밖에서 사용할 수 없습니다. VC++6.0은 가능했습니다.

        - 반환 값을 정의하지 않았을 경우 VC++6.0 은 기본 int로 선언되었지만, VS2010에서는 에러가 납니다.


    b. MFC 
    관련 오류 
        
    클래스/함수/메시지 헨들러 형태 및 정의 변경으로 인해 발생합니다.
        최신 MSDN을 참조하여 VS2010 MFC 에 맞게 수정해야 합니다.

        핸들러 오류 예제)

        ON_WM_NCHITTEST -> LRESULT OnNcHitTest(CPoint point)

        ON_MESSAGE -> LRESULT OnProgressing(WPARAM wParam, LPARAM lParam)


    c. 
    오버로드 된 함수 문제 
        2010에서는 함수의 다형성을 지원하기 위해, 많은 함수들이 오버로드 되었습니다.
        즉, 인자값의 타입만 바뀌어서 함수게 새롭게 제공된것들이 많다는 이야기지요
        그러다보니, 6.0에서는 그냥 넘어갔던 녀석들이 2010에 와서는 
    호출이 모호해지는 경우가  종종 발생합니다.
        적절하게 인자를 casting 하면 해결됩니다.

    d. 함수 포인터 정의의 경우 VC++6.0  default 값 정의가 가능했지만, VS2010에서는 불가능 합니다.

        예) typedef int (*FUNCPTR)(void *pClass, int iValue = -1); -> VC++6.0 가능 / VS2010 불가능.

     VS2010 C++ 에는 자료형이 long long(__int64와 같음), long double 형이 존재하며,

        이런 자료형으로 함수가 오버로딩 되거나 새롭게 변경된 함수가 많습니다.

        참고로 VS2010 CFile Class Length 관련 데이터는 ULONGLONG(unsigned long long) 자료형을 사용하여
        
    대용량을 지원합니다.

     

    4. 컴파일 경고


    a. VC++2005 
    이상에서는 C 표준 함수들 대신 보안 함수 사용을 권장합니다
        
    보안 함수는 접미사 _s 가 붙습니다.

        보안 함수를 사용함으로써 메모리 관련 문제를 근본적으로 막을수 있습니다.

        strcpy 대신 strcpy_s, scanf 대신 scanf_s 등의 사용을 권장하며기존 함수 사용시 Warning을 발생시킵니다.

       _CRT_SECURE_NO_WARNINGS define을 사용함으로써 Warning을 무시할수 있습니다

    b. warning C4996: '기존 함수 명': The POSIX name for this item is deprecated. Instead, 
        use the ISO C++ conformant name: '
    교체 함수명'.

       위와 같은 경고시에는 교체 함수 명"의 함수를 써서 작업해주면 됩니다.

    c. Type Library 경고 
        다양한 함수들이 추가됨에 따라타입라이브러리를 불러올 때
        
    라이브러리내에 같은 이름의 함수가 존재할 가능성이 많아져 충돌이 발생하게 됩니다
        
    적절하게 rename을 해줘야 합니다그렇지 않으면 실제 해당 함수를 사용할때 에러가 발생합니다.


    5. 릴리즈 테스트


    변환과정만 마치면 실행은 똑같이 될거라고 생각했다면 오산입니다.
    빌드후 생성된 제품이 사용하는 모듈도 변경되었기 때문에 (예-MFC dll)
    visual 2010용 배포모듈도 함께 배포해야 하며, 
    그전에 제대로 동작을 하는지 꼭 확인해봐야 합니다.
    6.0에서 잘되던 것이, 변환하고 나서 안될 경우도 수두룩합니다.
    해결방법은 다 있으니, 차근차근 해결해나가면 됩니다.


    6. 그 이외의 참고 사항

    소스를 6.0용과 2010용으로 동일하게 사용하기 위해서는 _MSC_VER define을 사용하도록 합니다.

    아래 방법이 컴파일러 조건 컴파일에 보편적으로 사용되는 방법입니다.

     

    컴파일러 버전별 _MSC_VER 값은 다음과 같이 정의되어 있습니다.

    1000 : Visual C++ 4.x

    1100 : Visual C++ 5

    1200 : Visual C++ 6

    1300 : Visual C++ .NET

    1310 : Visual C++ .NET 2003

    1400 : Visual C++ .NET 2005

    1500 : Visual C++ .NET 2008

    1600 : Visual C++ .NET 2010


    소스예제)

    #if  _MSC_VER >= 1600

               HANDLE hHandle = Create( a, b, c, d ) // VS 2010

    #else

               HANDLE hHandle = Create( a, b, c ); // VC++6.0

    #endif


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

    출처: http://www.devpia.com/Maeul/Contents/Detail.aspx?BoardID=51&MAEULNO=20&no=8221&page=4


     VC++ 6.0 -> VC++ 2008 변환 사례 

     | VC++ 일반 2009-01-20 오후 4:56:46    이기호 (fleem)   번호: 8221 / 읽음:6,833


    안녕하세요.

    매번 DEVPIA에서 정보만 얻어가다가 정보글을 한번 올려봅니다.

    VC++ 6.0 에서 개발되었던 프로그램을 VC++ 2008로 변환하면서 생겼던 에러입니다.

    확인하시고 업무에 도움이 되셨으면 좋겠습니다.

    혹시 지적하실 부분이 있으면 꼭 달아주시면 감사하겠습니다.

     

    1. error C2065 (변수 선언 부분)

    for (int i;i<MAX;i++)과 같이 for, if, while 등의 조건 문에 선언된 변수는 VC++ 2008에서 error C2065를 발생시킵니다. 정확히는 처음 변수가 선언된 조건 문에서는 문제 없이 돌아가지만 이후 변수를 재사용하고자 할 경우 선언 없이 사용하면 에러가 발생합니다. 변수를 조건 문 밖에서 선언하면 에러가 사라집니다.

     

    2. error C2440 (Message Map 관련 함수 Return 값 변환)

    소스코드에 정의되어 있는 Message Map의 일부 함수들의 반환 값이 VC++ 2008에서 error C2440를 발생시킵니다. 기존에 이 함수들을 Void 형으로 선언하여 사용해도 문제가 없었으나 VC++ 2008에서는 에러를 발생시키기 때문에 반환형을 LRESULT로 바꾸어 주어야 합니다. 또한 함수 내부에서도 Return 값을 선언하여야 에러 없이 프로그램이 실행됩니다.

     

    3. error C2668 (함수 오버로딩 부분)

    VC++ 2008은 오버로딩에 매우 민감하게 반응하여 VC++ 6.0에서 허용되던 것이 에러를 발생시킵니다. 예를 들어 Pow 함수의 경우 Pow 함수가 double Pow(double x, double y)로 정의되어 있으므로

    Pow(2,i)로 사용할 경우 에러가 발생합니다. 첫 번째 인자 2가 double 형이 아니기 때문인데, 2.0로 바꾸어 주면 에러가 발생하지 않습니다. 함수를 사용할 때, 오버로딩 규정에 맞게 모든 인수를 입력해야 에러가 발생하지 않습니다.

     

    4. Warning 발생 관련

    VC++ 2008으로 변환하면서 많은 Warning가 발생하는데, 우리 설비 프로그램에서 발생하는 것은 크게 두 가지입니다. 첫 번째로 Warning 4996은 swprtinf, strcpy 등 문자열을 다루는 crt 함수에 취약점이 많은 관계로 MS에서 새롭게 보완한 crt 함수를 사용하기를 권장하는 경고입니다. 함수 명 뒤에 '_s'를 붙인 보안 강화 함수로 대체하여 사용하거나(ex, swprintf_s) 또는 #pragma warning(disable:4996) 을 선언해주어 경고를 무시하면 해결됩니다. #pragma warning(disable:4996) 선언 시 "stdafx.h"에 선언해주면 편리합니다.

    두 번째로 Warning 4819는 ANSI로 인코딩된 소스코드를 사용하는 프로그램이 Visual Studio 2005 이후의 한글 버전에서 경고를 발생시키는 겁니다. 주로 주석 등에 한글 또는 외국어로 작성한 것이 문제가 된다고 하는데, 소스코드를 유니코드로 새로 저장, 해당 외국어를 삭제 또는 첫 번째와 같이 #pragma warning (disable : 4819) 을 선언하여 경고를 무시하면 해결됩니다.

     

    5. 멀티코어 CPU를 활용한 /MP(Build with Multiple Processes)

    Visual Studio 2005 Service Pack 1부터 멀티코어 CPU를 활용한 Native C++ 컴파일이 가능하다고 하며 전체 Build 시간을 줄여 준다고 합니다.


    위의 그림과 같이 프로젝트 속성 → 구성 속성 → C/C++ → 명령줄 에 "/MP" 명령을 추가해주면 Build with Multiple Processes 가 수행됩니다. 또, 아래와 같이 프로젝트 속성 → 구성 속성 → C/C++ → 코드 생성에서 "최소 다시 빌드 가능" 을 "아니요"로 바꾸어 주어야 "/MP"가 제대로 동작합니다.



    7. 기타 세부 사항

    a. std::vector iterator 관련 사항

    Vision 쪽에서 사용하던 std::vector이 VC++ 2008로 변환 시 문제가 발생합니다.

    디버깅 시에는 잡히지 않지만 프로그램 실행 시 프로그램 오류가 발생합니다.

    std::vector을 사용할 때, iterator 를 선언하여 for문을 사용하는 경우,

    for (i = m_vectorData.begin(); i < m_vectorData.end(); i++)

    와 같이 사용할 경우 문제가 없지만

    for (i = m_vectorData.end() - 1; i >= m_vectorData.begin(); i--)

    와 같이 역순으로 사용할 경우 오류가 발생합니다. 역순으로 iterator를 사용할 경우 reverse_iterator 를 대신 선언하여 사용해야 하며, begin()과 end()도 rbegin() rend()로 바꾸어서 사용해야 합니다.

     

    b. SystemParametersInfo  관련 문제

    VC++ 2008에서 SystemParametersInfo 이 문제가 발생했었는데 문제가 발생한 부분은 다음과 같이 SystemParametersInfo 을 이용하여 시스템 설정을 읽는 부분이었습니다.

    VC++ 2008에서는 WINVER을 Windows XP로 정의하지 않으면 Vista로 기본 설정하는데, Vista 설정에서 문제가 발생합니다.



    위의 부분 중

    ncm.cbSize = sizeof(NONCLIENTMETRICS); 을

    ncm.cbSize = sizeof(NONCLIENTMETRICS) - sizeof(ncm.iPaddedBorderWidth);

    으로 바꾸어 주면 문제가 해결됩니다. VC++ 2008이 Windows Vista 기반의 개발환경(대화상자 등)을 제공하는데 이 부분에서 4 Pixel(iPaddedBorderWidth) 만큼 더 크기를 사용한다고 합니다. 그래서 SystemParametersInfo을 사용할 때, cbSize의 크기를 iPaddedBorderWidth 만큼 빼야 SystemParametersInfo가 정상적으로 작동합니다. 그러나 VC++ 6.0 버전에서 Windows XP로 정의하여 사용할 경우 (#define WINVER 0x0501) 원래대로

    ncm.cbSize = sizeof(NONCLIENTMETRICS); 을 사용해야 합니다.

     

    c. Windows, Visual Studio Version 설정

    프로그램에서 Windows나 Visual Studio의 Version을 확인할 경우 다음의 설정을 사용하시면 됩니다.


    Macro

    WINVER

    _MSC_VER

    설명

    Using the Windows Headers

    Visual Studio Version

    Version

    /Number

    Windows Server 2008

    0x0600

    VC 9.0 (2008)

    1500

    Windows Vista

    0x0600

    VC 8.0 (2005)

    1400

    Windows Server 2003 with SP1, Windows XP with SP2

    0x0502

    VC 7.1 (2003)

    1310

    Windows Server 2003,

    Windows XP

    0x0501

    VC 7.0 (2002)

    1300

    Windows 2000

    0x0500

    VC 6.0 (1998)

    1200



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

    출처: http://blog.naver.com/s981727/10099326751

    MFC VS6.0에서 VS2008로 컨버전시 고쳐야할 내용들|작성자 하드코딩



    1. CRT 함수를 더 안전하게 쓰기위한 _s가 붙은 Secure함수를 쓰게되었음

    Security-Enhanced Versions of CRT Functions

    http://msdn.microsoft.com/ko-kr/library/wd3wzwts(v=VS.80).aspx

    여기가면 CTR함수 리스트를 볼 수 있음

     

    =====================================================================================

    아래글 출처: http://frostguy.tistory.com/12?srchid=BR1http%3A%2F%2Ffrostguy.tistory.com%2F12


    fopen 과 fopen_s 의 차이 및 사용시 주의점

    VS 2005 로 넘어오면서 일반적인 문자열 함수가 아닌 _s 가 붙은 함수의 사용을 권장하게 되었으며


    이를 사용하지 않을경우 warning 이 발생한다.  


    strcpy -> strcpy_s

    fopen -> fopen_s  

    처럼 _s 를 붙이게 되는데, fopen 을 fopen_s 로 그냥 변환하게 되면 큰 문제가 발생한다.


    파일을 한번만 열게 되면 상관이 없지만, 똑같은 파일을 여러번 열고 닫을 경우에는  최초에 파일을 열때는 상관없지만, 2번째 파일 Open 시부터는 Permission Denied 라는 errno 를 반환하며 파일을 쓸 수가 없게 된다.  


    아래 fopen_s 의 msdn 을 참고하면

    http://msdn.microsoft.com/ko-kr/library/z5hh6ee9(VS.80).aspx


    Files opened by fopen_s and _wfopen_s are not sharable. If you require that a file be sharable, use _fsopen, _wfsopen with the appropriate sharing mode constant (for example, _SH_DENYNO for read/write sharing).

    fopen_s 는 파일을 공유할 수가 없다고 적혀있다.


    파일을 공유하기 위해서는 _fsopen 을 사용하면된다


    if ( (fp=fopen(strPath, "wb")) == NULL) {AfxMessageBox("Cannot Open File");} // 정상 동작 

    errno = fopen_s(&fp, strPath, "wb") 

    if (errno != 0) {AfxMessageBox("Cannot Open File");} // 오류...

    if ( (fp=_fsopen(strPath, "wb", _SH_DENYNO)) == NULL) {

             AfxMessageBox("Cannot Open File");

    } // 이와 같이 변경...

    ------------Posted by frostguy-----------------

     

    ========================================================================================

     2. redefinition 에러: for문 사용 시 

     for(int i = 0; i < 100; i++){

      k++;

     }

     for(i = 0; i < 100; i++){

      k--;

     }

    기존 VS6.0에서는 위 문법처럼 사용 가능했으나 VS2008에서는 에러 발생

    => for문안에 선언한 변수는 For문 내에서만 사용가능한 지역 변수가 되어버림


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

    출처: http://blog.naver.com/jinugi77/100126754722

    프로젝트 변환후 빌드시 MSB8012 경고

    2011/04/25 16:39   작성자 디트로이



    VS2008 프로젝트를 2010으로 변환후 빌드 했는데..

    MSB8012 워닝이 뜨길래 뭔가 하고 찾아봤더니;;;

     

    "Object 파일을 생성하는 Output 폴더와 바이너리 파일을 생성하는 경로가 다른 경우 MSB8012 경고가 발생합니다."

    라는 문구를 찾을 수 있었다;

     

    즉,

    Target Path와 실제 바이너리 생성 경로가 다르기 때문이라고 하는데...

     

    쉽게 얘기하면

    프로젝트 옵션의

    General->Output Directory 에 설정된 내용과

    Linker->General->Output File 에 설정된 내용이 다르다는 소리다.

     

     

    해결방법은

    모든 configuration 의 Linker->Output File은

    $(OutDir)$(TargetName)$(TargetExt)

    로 고정시켜두고

    $(OutDir) : General ->Output Directory

    $(TargetName) : General -> Target Name

    $(TargetExt) : General -> Target Extension


    Property Page ->General내의 아래 옵션을 

    General->Output Directory

    General->Intermediate Directory

    General->Target Nmae

    Configuration별로 원하는 디렉토리와 바이너리명을 입력하면 된다.


     

    실제로 변경하고 빌드해보니 워닝이 사라짐....;




    나 같은 경우에는 실행파일은 모두 bin 폴더에 넣고

    obj 파일은 build\ 폴더안에 configuration 별로 넣기 때문에 아래와 같이 설정한다.


    Output Directorey =====> $(SolutionDir)\Bin\

    Intermediate Directory => .\Build\$(Configuration)\

    Target Name =>

    multi-byte release : $(ProjectName)

    multi-byte debug : $(ProjectName)d

    unicode release : $(ProjectName)u

    unicode debug : $(ProjectName)ud



Designed by Tistory.