CRT 함수의 보안버전 Security-Enhanced Versions of CRT Functions - MSDN
warning
C4996: 'strcpy': This function or variable may be unsafe. Consider
using strcpy_s instead. To disable deprecation, use
_CRT_SECURE_NO_WARNINGS. See online help for details.
버퍼의 길이체크를 하기 위한 _s접미사가 붙는 보안 버전의 CRT 함수가 추가되었다.사용방법은 기존 함수에 _s를 붙이고 버퍼의 길이를 인자로 더 추가해주면 된다.당장은 VC에만 존재하지만 앞으로 C++표준에 추가될 수 있다고 한다.
참고사항 1. _s관련 함수는 errno_t를 반환하게 변경되었다.(에러발생) 2. _CRT_SECURE_CPP_OVERLOAD... 관련 3개의 define을 사용하면 버퍼가 배열형일 경우 Template overloads를 이용해서 기존 코드를 자동으로 _s관련 함수로 변경할 수 있다. Default 값과 설명 _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 1 -> secure함수에 길이 인자관련을 생략해준다. _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 0 -> 기존함수 지원 ex) strcpy _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT 0
-> 길이체크하는 기존함수 지원 ex) strncpy 위와같이 편한 방법이 있지만 포인터형의 버퍼변수 일경우는 기존과 같이 길이값을 인자로 넣어야 한다. char a[100]; // 가능 strcpy_s(a, "hello");
char * p = new char[100]; // 불가능(컴파일 에러) strcpy_s(p, 10, "hello");
위와 같은 코드는 혼란만 올뿐이다. 결론은 secure함수를 사용할꺼라면 인자값을 사용하지말고 overload함수도 사용하지 말자.
#ifndef _TIME_T_DEFINED
typedef long time_t; /* time value */
#define _TIME_T_DEFINED /* avoid multiple def's of time_t */
#endif
/////////////////////////////////////////////////////////////////////////
// VC9(2008)
// c:\program files\microsoft visual studio 8\vc\include\crtdefs.h
#ifndef _TIME64_T_DEFINED
#if _INTEGRAL_MAX_BITS >= 64
typedef __int64 __time64_t; /* 64-bit time value */
#endif
#define _TIME64_T_DEFINED
#endif
문제점
이부분은 기존 long형으로 처리되던 부분들이 에러없이 자동으로 64비트로 변경되므로 32비트로 처리되던 코드들은 메모리주소가 밀려서 쓰레기값으로 처리될수 있다.
해결방법(임시)
_USE_32BIT_TIME_T 를 정의한다.
MSDN을 참고해보면 위와 같이 define해놓으면 time_t를 32비트로 쓸수 있다.
사용자 정의(User-Defined) 메세지
User-Defined Handlers - MSDN
아래 내용은 기존에 정의되어 사용되고 있던 것이지만 VC6에서 대충 넘어가던것을 2005부터는 정확하게 사용되어야 하는 것들이다.
1. ON_MESSAGE
MFC에서 사용자 정의 메세지를 사용시 User-Defined Handlers의 원형은 아래와 같은데
afx_msg LRESULT memberFxn( WPARAM, LPARAM ); VC6에선 반환값을 void형으로 선언하고 사용해도 문제가 없었지만 2005부터는 컴파일 에러가 발생한다
해결방법
1. ON_MESSAGE를 ON_MESSAGE_VOID로 변경한다.
-> AFXPRIV.H에 선언되어 있는 ON_MESSAGE_VOID를 사용하면 문제는 해결할 수 있지만 AFXPRIV.H파일 자체가 MFC 버젼이 바뀔경우 예고없이 바뀔 수 있는 파일이므로 조심해야하고 위매크로를 사용시 함수의 인자값이 이상하다는 글을 본적이 있으므로 사용시 주의하자. 매크로의 선언은 아래와 같다.(VC6,2008 sp1)
// like ON_MESSAGE but no return value
#define ON_MESSAGE_VOID(message, memberFxn) \
{ message, 0, 0, 0, AfxSig_vv, \
(AFX_PMSG)(AFX_PMSGW)(void (AFX_MSG_CALL CWnd::*)(void))&memberFxn },
2. LRESULT를 반환하게 함수를 변경한다.
-> 이게 표준이니 이렇게 사용하자.
2. ON_THREAD_MESSAGE ON_THREAD_MESSAGE - MSDN
CWinThread를 상속한 클래스내에서는 ON_MESSAGE가 아닌 ON_THREAD_MESSAGE를 사용해야한다.
사용법은 동일하지만 함수원형에 반환 값이 없다. afx_msg void memberFxn( WPARAM, LPARAM );
매크로의 선언을 비교해보자.(AFXMSG_.H)
// for Windows messages
#define ON_MESSAGE(message, memberFxn) \
{ message, 0, 0, 0, AfxSig_lwl, \
(AFX_PMSG)(AFX_PMSGW)(LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM, LPARAM))&memberFxn },
속성 -> 구성속성 -> C/C++ -> 언어 -> wchar_t를 기본 제공 형식으로 처리 -> 아니요
error C2668(함수 오버로드)
함수 오버로드에 대한 묵시적 형변환을 사용할 수 없다. VC6에선 상관없던 코드가 최신툴에선 error를 발생한다.
error C2668: 'pow' : 오버로드된 함수에 대한 호출이 모호합니다.
error C2668: 'sqrt' : 오버로드된 함수에 대한 호출이 모호합니다.
위의 에러는 double pow(double x, double y)인 pow함수등을 pow(2,2)같이 호출했을때 발생한다. 이때는 형변환을 하거나 숫자뒤에 '.'를 표시해서 실수로 만들어준다. 표준이므로 지키자.
※표준 준수를 더욱 강화하기 위해
pow의 오버로드 double pow(int, int)가 제거되었습니다. - MSDN
-> int형의 인자를 받던 pow함수가 제거되었다. 그리고 _Pow_int라는 템플릿함수가 추가되었다.
VC 프로젝트 기본 설정
WINVER 설정
VC6프로젝트를 2005이상으로 업그레이드시 WINVER 가 정의 되지 않아 Default 값을 설정한다는 메세지를 볼수 있다.
WINVER not defined. Deafaulting to 0x0502 (Windows Server 2003)
-> 2008은 Vista가 기본이다.
VS2005이상으로 프로젝트를 새로 생성시는 stdafx.h에 #include "targetver.h"가 선언되며 이곳에 프로젝트가 최소로 지원하는 플랫폼을 정의해놨다.
참고
WINVER값이 잘못설정되어 있으면 API나 라이브러리에서 윈도우의 버젼이 잘못 설정되어 이상하게 동작하거나 에러가 발생할 수도 있으므로 업데이트 후 WINVER관련을 잘 체크하자.
->_WIN32_WINNT값을 0x0500으로 선언하고 필자의 경우 CFileDilog를 사용하면 error가 발생한다. 이유는 OPENFILENAME구조체의 선언때문인데 아래 링크를 참조하자. MFC 프로젝트를 Visual C++ .NET 이나 대상 운영 체제에서 Visual C++ 2005 변경 이식 - MSDN
99%'s Code
위 정리된 사항을 필자는 아래코드로 헤더파일 하나에 넣고 stdafx의 상위에서 설정해서 사용한다.
sy는 필자 이름이므로 헷갈리지 말자 ㅎㅎ
// syDef.h
#pragma once
///////////////////////////////////////////////////////////////////////////////////////////////////////////
// 최소로 지원하는 플랫폼 정의
// Modify the following defines if you have to target an OS before the ones
// specified in the following code. See MSDN for the latest information
// about corresponding values for different operating systems.
#ifndef WINVER // Permit use of features specific to Windows 95 and Windows NT 4.0 or later.
# define WINVER 0x0400 // Change this to the appropriate value to target
#endif // Windows 98 and Windows 2000 or later.
#ifndef _WIN32_WINNT // Permit use of features specific to Windows NT 4.0 or later.
# define _WIN32_WINNT 0x0400 // Change this to the appropriate value to target
#endif // Windows 98 and Windows 2000 or later.
#if (_MSC_VER > 1200) // VC6 초과
# ifndef _WIN32_WINDOWS // Permit use of features specific to Windows 98 or later.
# define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target
# endif
#endif // _MSC_VER // Windows Millennium Edition or later.
#ifndef _WIN32_IE // Permit use of features specific to Internet Explorer 4.0 or later.
# define _WIN32_IE 0x0400 // Change this to the appropriate value to target
#endif // Internet Explorer 5.0 or later.
// #include "targetver.h" -> .net툴에서 위코드가 포함된 헤더파일
// http://msdn.microsoft.com/en-us/library/aa383745(VS.85).aspx - Using the Windows Headers(MSDN)
///////////////////////////////////////////////////////////////////////////////////
// Visual C++ 8이상 세팅
//#define SYUTIL_USE_CRT_SECURE // CRT 보안관련 함수 사용
#define SYUTIL_NOTUSE_NONSTDC_NO // POSIX관련 CRT사용안함
#define SYUTIL_USE_32BIT_TIME_T // time_t를 32비트로 사용함
// VC8(VS2005) 이상 컴파일러설정.
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
// 최신버젼의 VC라이브러리 사용
// Redistributing an Application and Binding It to Specific Libraries - MSDN
// http://msdn.microsoft.com/en-us/library/cc664727.aspx
# ifdef _BIND_TO_CURRENT_VCLIBS_VERSION
# undef _BIND_TO_CURRENT_VCLIBS_VERSION
# define _BIND_TO_CURRENT_VCLIBS_VERSION 1
# else
# define _BIND_TO_CURRENT_VCLIBS_VERSION 1
# endif
// 안전한 문자열 사용(오버플로우 방지)
// Using the Strsafe.h Functions
// http://msdn.microsoft.com/ko-kr/library/ms647466(en-us,VS.85).aspx
# define STRSAFE_NO_DEPRECATE
//#pragma warning(disable : 4995)
// time_t 64비트 처리
// Time Management - MSDN
// http://msdn.microsoft.com/ko-kr/library/w4ddyt9h.aspx
# ifdef SYUTIL_USE_32BIT_TIME_T
# define _USE_32BIT_TIME_T
# endif // SYUTIL_USE_32BIT_TIME_T
// 유니코드 형식으로 저장하라는 경고 무시 -> VS 버그임
// http://support.microsoft.com/kb/912790
# pragma warning(disable: 4819)
#endif // _MSC_VER
#if _MSC_VER == 1500
// Visual C++ 2008(9.0)
#elif _MSC_VER == 1400
// Visual C++ 2005(8.0)
#elif _MSC_VER == 1310
// Visual C++ .NET 2003(7.1)
#elif _MSC_VER == 1300
// Visual C++ .NET 2002(7.0)
#elif _MSC_VER == 1200
// Visual C++ 6.0
#elif _MSC_VER == 1100
// Visual C++ 5.0
#endif
정리중...
///////////////////////////////////////////////////////////////////////////////////////////////////////
// 문자 집합이 기본 유니코드이다.
속성 -> 구성속성 -> 일반 -> 프로젝트 기본값에서 문자 집합 -> 멀티코드 문자 집합 사용
///////////////////////////////////////////////////////////////////////////////////////////////////////
// 런타임라이브러리(CRT)이 기본 /MD, CRT라이브러리에 대해서는 고민해보아야 하고
// 기존라이브러리들과 맞춰주는게 좋다.
속성 -> 구성속성 -> C/C++ -> 언어 -> 런타임 라이브러리 -> /MT
///////////////////////////////////////////////////////////////////////////////////////////////////////
// 비증분 링크
LINK : warning LNK4076: '.\Debug/IIS.ilk' 증분 상태 파일이 잘못되었습니다. 비증분 링크합니다.
프로젝트 -> 속성 -> 링커 -> 일반 -> 증분 링크 사용 -> 아니요(/INCREMENTAL:NO)
///////////////////////////////////////////////////////////////////////////////////////////////////////
// 증분 링크
LNK4075: '/EDITANDCONTINUE'이(가) '/INCREMENTAL:NO' 사양으로 인해 무시됩니다.
프로젝트 -> 속성 -> 링커 -> 일반 -> 증분 링크 사용 -> 예(/INCREMENTAL)
증분링크란?
obj를 합치는과정에서 메모리배치랑 순서 함수들 코드, 데이터 영역등을 계산하게 되는데 이걸 매번 재계산하게되면 시간이 오래 걸리게되죠
그래서 변한건만 재계산하는 과정을 말합니다. 위의 속성은 "증분 링크" 하겠다는거죠.간간히 이전obj가 껴있어 문제가 생기는데
이땐 rebuild all해서 풀링크 하면된다고 하네요 ^^;;
배포시에는 Dependency Walker(depends.exe)와 같은 도구를 사용하여 종속 DLL의 목록을 확인한다. 또한 2005이상의 VS(Visual Studio)는 manifest를 꼭 확인해서 사용한 dll과 버전을 확인해야한다.
VC++ Library 그림 1(VS2005 기준)
그림은 VS2005를 기준으로 하고 있지만 다른 버젼도 위와 같은 규칙으로 명명되고 있다. xx는 각각의 버전을 나타내며 플랫폼 별로 x86,ia64,x64용이 따로 있다. u는 Unicode버전을 나타내고 m은 managed code를 사용했을때 사용되며 배포시 .NET Framework이 필요하다. 배포폴더에 manifest가 존재하면 같이 배포한다.
■ IA64(EPIC instruction set): 인텔 Itanium 프로세서부터 채용된 새로운 명령어 집합. 기존 IA32와 호환이 되지 않는다. EPIC(Explicitly Parallel Instruction Computing) instruction set을 가지며, 많은 차이점이 있겠지만, predicated instructions을 지원한다는 것과 최소 6개의 floating point unit은 기억할만하다.
■ X64: AMD Opteron 프로세서부터 채용되었고, AMD64, Intel64(EM64T)으로 소개되었지만, 지금은 X64로 보통 부른다. IA32를 64-bit을 지원하기위해 확장한 것으로, IA32와 완전한 호환을 가지는 Compatibity mode와 64-bit mode를 지원한다. 우리가 흔히 말하는 64-bit 모드이다.
- 64-bit mode에서는 명령어에 8-bit REX prefix를 붙여서, 64-bit 레지스터를 사용할 수 있다. 또한, 64-bit mode에서는 레지스터 개수도 기존의 8개에서 16개로 다음과 같이 늘어났다. - Long mode - Compatibility mode: eax, edx, exc, ebx, esi, edi, esp, ebp - Long mode - 64-bit mode: rax, rdx, rxc, rbx, rsi, rdi, rsp, rbp, r8,r9,r10,r11,r12,r13,r14,r15
- AMD64에서는 Operating mode로서 총 5개가 지원된다. - Long mode - Compatibility mode - Long mode - 64-bit mode - Legacy mode - Protected mode - Legacy mode - Virtual 8086 mode - Legacy mode - Real mode
- AMD64의 어드레스는 레지스터 값은 64bit으로 부호확장되어 보이며, 현재는 다음과 같은 범위를 가진다. - physical address: 1TB (40-bit) - virtual address: 256TB (48-bit) : 부호확장이 되었으므로, 유효한 virtual address는 다음 두 영역으로 된다. - 0x0 ~ 0x00007FFF_FFFFFFFF - 0xFFFF8000_00000000 ~ 0xFFFFFFFF_FFFFFFFF
Side by Side Asembly
2005부터는 side by side asembly라는 기술이 도입되어 VC관련 라이브러리들이 Windows 디렉토리 밑에 WinSxS (Windows Side-by-Side)라는 공유 폴더(native assembly cache)로 관리된다. side by side asembly는 DLL 충돌문제를 해결해서 각각의 어플리케이션에게 독립적인 DLL환경을 제공하기 위한것으로 여러버젼의 DLL들이 등록될수 있다. 복잡한 이과정을 간단하게 해결하는 방법으로 VC8부터는 재배포 패키지(Redistributable Package)라는 배포용 설치파일이 도입되어 공용 라이브러리를 자동으로 설치/등록해준다. 또한 프로젝트에서 자동 생성해주는 Manifest Flie에 사용된 DLL과 버전이 자동으로 입력되니 배포시는 꼭 확인하도록 한다.
프로그래머나 사용자입장에선 관련 DLL을 포함만 하면 되는 기존 작업과 달리 설치파일이 하나 더생겼으니 귀찮은 작업이지만 최신 운영체제의 기본 관리 방법이기도 하고 .Net의 기술과도 무관하지 않으니 지금 정리하도록 하자.
최신 라이브러리를 Manifest에 기술하기(VC9)
배포방법을 알아보기 전에 알아두어야 할사항이 있다. VC9는 VC8과 달리 sp1같은 최신 라이브러리를 개발자PC에 설치했다고 해도 프로젝트가 최신라이브러리를 사용한다고 명시해주지 않으면 기존라이브러리를 기본으로 사용하므로 주의해야한다. 이것은 개발자가 sp1을 설치했어도 프로젝트는 기존 DLL버전을 사용하므로 배포시 sp1용 재배포 패키지를 사용하면 제대로 실행될 수 없음을 나타낸다. 방법은 아래와 같다.
'_BIND_TO_CURRENT_VCLIBS_VERSION'를 프로젝트 설정에서 선언해준다.
-> stdafx.h의 상단에 #define으로 입력해도 일반적인 프로젝트에선 상관없지만 프리컴파일드 헤더를 사용안하거나 외부라이브러리가 프로젝트에 미리 세팅되었을 경우 두개의 버전을 중복 사용하는 경우가 발생할 수 있으므로 프로젝트 설정에서 선언하길 권장한다. 이값은 CRT,MFC,ATL,OPENMP 4개의 '_BIND_TO_CURRENT...' 선언을 다 쓰겠다고 선언하는것이고 _BIND_TO_CURRENT_VCLIBS_VERSION의 기본값은 0으로 세팅되어있다.
2008에서 MFC프로젝트 생성시 자동으로 생성해주는 Manifest file이다. Manifest File의 종류는 External(외부)와 Internal(내부)가 있는데 VC프로젝트 기본설정으로 컴파일시 Internal로 Exe파일에 자동으로 포함된다. 위치는 파일의 거의 마지막 부분이고 일반적인 텍스트로 아래와 같이 보이므로 메모장 등으로 확인해보자.
배포방법 그림1과 참고에 MSDN링크가 2005의 공용DLL 목록과 설명이다. side by side asembly로 인해 배포문제가 좀 복잡해져서 depends 만을 확인해서 관련 DLL을 포함한다고 제대로 실행된다는 보장을 받을 수 없게되었다. 일반적인 방법과 재배포 패키지를 사용하는 방법을 알아보자.
1. 정적 라이브러리(Static Library)를 사용한다.
실행파일이 커지긴 하나 제일 간단하다. MFC 라이브러리를 사용시는 MFC라이브러리를 정적으로 포함하면 CRT도 자동으로 /MT로 변경된다. 용량은 기본 MFC 다이얼로그 프로젝트가 52k정도에서 308k 정도로 커진다.
ATL과 OPENMP까지 사용한다면 웹에서 배포되는 ActiveX 같은 상황이면 용량때문에 고민해봐야할 문제이고 정적라이브러리도 동적라이브러리와 똑같다고는 하지만 몇가지 버그가 있으므로 주의하자.
2. Manifest를 참조해서 기본 DLL을 배포한다.(Private Assembly)
배포방법이 바뀌었다곤 하나 관련 DLL을 포함해서 배포할수도 있다. VS의 설치폴더에 있는 공용DLL(Private Assembly)을 같이 배포하면 된다. 우선 Manifest로 사용한 DLL을 확인한후 "..\Microsoft Visual Studio X\VC\redist\"에서 관련 DLL(그림1참고)을 프로젝트 폴더에 포함한다. 이방법도 쉬운편이긴 하나 3MB정도의 크기인 재배포 패키지에 비하면 사용하는 라이브러리가 많을 수록 용량이 너무 큰편이다.(기본 CRT와 MFC라이브러리만 4.76MB - 2008sp1 기준)
3. 인스톨쉴드(Install Shield), 설치 프로젝트를 이용해서 재배포 패키지가 자동으로 설치되게 한다.
-> 모든 프로젝트를 이렇게 만들긴 좀 귀찮다;;
4. .Net Framework(최신)를 설치한다.
.Net Framework를 설치하면 CRT관련 DLL만 같이 설치된다.(fx 3.5설치시 8.0과 9.0이 같이 설치됨)
managed로 컴파일했다면 .Net Framework는 필수이므로 고민할 문제가 아니지만 용량이 100메가도 훨씬 넘는다..;;
재배포 패키지(Redistributable Package)
재배포 패키지는 Windows Installer 3.1을 필요로 하는 인스톨 파일이다. 한번 실행하기만 하면 자동으로 설치되지만 사용자 입장에선 불편한 사항이다. 하지만 Windows Installer의 Command line을 이용해서 몰래설치하는 방법이 있다. 이를 이용해서 런처형식의 프로그램을 만들면 Windows Installer 3.1의 설치유무와 재배포 패키지 자동 설치를 하고 프로그램을 실행하게 할 수 있다. 좀더 범용적으로 사용하면 파일로 설치필요 설정값을 받아와서 COM관련 등록이나 웹배포시 ActiveX등록등을 자동으로 하게 만들수도 있다. 관련 소스가 정리되는 대로 블로그에 올리도록 하고 우선 VC6으로 재배포 패키지의 설치유무와 자동 실행하기 위한 코드를 설명하겠다.
1) 재배포 패키지 설치 유무 확인
재배포 패키지는 설치폴더에서 받거나(..\Microsoft Visual Studio X\SDK\v2.0\BootStrapper\Packages\vcredist_x86) 아래 링크를 통해 MS의 다운로드에서 받는다.
2-1) 일반 적인 인스톨러 사용처럼 추가/제거 목록에 표시되므로 레지스트리 값으로 확인할 수 있다.
"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\ProductCode"
2-2) MsiQueryProductState API를 이용해서 확인한다.
리턴값으로 INSTALLSTATE_DEFAULT인지만 확인하면 설치유무를 판단할 수 있다.
위코드는 영문 버전이고 한글버전은 다르고 설치시 중복될수 있다. ProductCode와 추가/제거에 표시되는 이름외에 다른점은 없다. 참고로 2008 sp1 x86 한글버전은 {887868A2-D6DE-3255-AA92-AA0B5A59B874}이다.
Window7에서도 테스트 했음.
VS2008
2008에서는
<full path>\vcredist_x86.exe /qb
<full path>\vcredist_x86.exe /qb!
<full path>\vcredist_x86.exe /q -> 화면에 전혀 보이지 않음
위 3가지 방법중 선택해서 사용하면 되며 Vista이상의 경우는 /q로 설정해도 UAC가 보이므로 필자는 /qb!를 사용한다. 직접 사용해보고 판단하자.
1. clock()
ANSI C 함수이며 time.h에 정의되어 있어 UNIX/Linux에서도 잘 수행된다.
현 프로세스가 실행한지 얼마 되었는지에 대한 CPU 시간을 clock tick의 개수 단위로 반환해준다.
#include "time.h"
// 시작
clock_t beginTime;
clock_t endTime;
beginTime = clock();
// 작업 수행
// 수행 종료
endTime = clock();
// 값 출력
CString tmp = _T("");
tmp.Format("작업 수행 시간 - clock() : %5.3f",
(double)(endTime - beginTime) / CLOCKS_PER_SEC);
2. timeGetTime(), GetTickCount()
1/1000초 단위로 정확하게 제어할 수 있는 타이머가 바로 멀티미디어 타이머이다. 자세하게 말한다면 Timer Event Callback Notification 메커니즘을 적용하고 있는 타이머이다. 이 멀티미디어 타이머의 단점은 많이 사용할수록 시스템에 상당한 부하를 일으키며, 이외에 제대로 사용하지 못하면 예측할 수 없는 결과가 초래된다고 알려져있다. 이 타이머는 수행 시간 기준으로 일정한 시간이 되면 어떠한 행동을 취하는데 사용된다.
GetTickCount() 함수와 timeGetTime() 함수의 차이점은 운영체제의 정밀도에 차이가 있다. 예를 들어 GetTickCount()함수는 윈도우 9X에서는 기본으로는 약 55 밀리 초이지만, timeGetTime() 함수는 윈도우 9X에서는 1밀리 초이다. 따라서 부정확해질 수 있다. 그러므로 결국 timeGetTime()을 사용하는 게 유리하다. 다만 두 함수는 윈도우 2000, XP등 으로 올라갈수록 정밀도가 현격하게 벌어지게 된다. 따라서 최소의 타이머 해상도를 결정하는 timeBeginPeriod()함수와 timeBegindPeriod에 의해 만들어진 타이머 해상도를 제거하는 timeEndPeriod() 함수를 추가해 줌으로써 정밀도를 보정해 줄 수 있다. 정확한 시간을 구하지 않는 다는 가정 하에서는 두 함수 중에서 편한대로 선택한다.
설치후 컴파일 에러가 날경우 Visual Studio 2008의 ATL 보안업데이트 이후 발생하는 컴파일 에러 문제
2005부터는 재배포패키지라는 개념이 도입되어 배포방법이 까다로워(?) 졌다. 서비스팩이 업데이트 될경우 재배포 패키지 또한
변경해줘야한다. 사용자 입장에선 이게 좀 불편한편인데.. 물론 대상 컴퓨터가 x86의 일반적인 CPU를 사용하는 환경이라면
재배포 패키지에서 사용하는 DLL만 가져온후 같이 배포하면 이문제가 거의 대부분 해결되기는 한다.
하지만 이번에 업데이트된 프로그램 배포시는 재배포 패키지가 항상 필요할 듯 하다. 아래 내용참고.
9.0.30729.1과 9.0.30729.4148 CRT를 둘다 필요로 한다. 버젼은 달라도 CRT의 이름은
다르므로 DLL만 포함하면 실행이 안된다. 그러므로 일반적으로 dll을 포함하던 방법으론 프로그램이 제대로 실행되지 않을 것이다.
배포할 일에 많은 개발자가 아무생각없이 자동 업데이트 했다가는 사무실이 뒤집어 질꺼다;(필자의 경험담? ㅡ.ㅡa)
ATL 보안업데이트 삭제
위와 같이 바뀌어도 인스톨쉴드에 파일 하나만 바꾸면 되는거 아니나는 분들에겐 할말 없지만 조금이라도 불편해서 삭제하고 싶은 분들은 참고하기 바란다.(아래는 필자의 경험담이며 공식문서 확인시 변경될수 있다)
위 보안 업데이트를 삭제하는 방법은 공식 문서에는 프로그램 추가/삭제에서 제거 해주면 된다고 명시되어 있다. 하지만 재배포
패키지 관련 업데이트만 목록에 존재하며 삭제를 해도 VS와는 전혀 상관없다. 윈도우 복원을 날짜를 되돌려도 설정은 바뀌지
않는다. 그래서 필자가 택한 방법은 VS를 전체 삭제하고 재설치 하는거였다 ㅡ.ㅡ; 전체삭제하고 재설치를 해도 기본 설정값들은
전부 남아있어서 크게 불편한점은 없었고 안전하게(?) 이전 버젼의 DLL을 사용한다.
위방법 적용후 필자의 결론은 추가/제거에서 관련 업데이트를 삭제후 기존에 사용하던 서비스팩만 재설치해도 문제가 해결될꺼같다는 거다.
인스톨에 대한 거부감과 DLL업데이트후 재배포 패키지를 설치해야된다는 말에 지대로 거부감 날려주신 클라이언트로 인해
이번업데이트에 대해 정리해본다. 사실 별 내용은 아닌데 결론은 개발자용 PC에 아무리 중요한 업데이트라도 아무생각없이 막
설치해서는 안된다는거다.(응?)
■ IA64(EPIC
instruction set): 인텔 Itanium 프로세서부터 채용된 새로운 명령어 집합. 기존 IA32와 호환이 되지
않는다. EPIC(Explicitly Parallel Instruction Computing) instruction set을
가지며, 많은 차이점이 있겠지만, predicated instructions을 지원한다는 것과 최소 6개의 floating
point unit은 기억할만하다.
■ X64:
AMD Opteron 프로세서부터 채용되었고, AMD64, Intel64(EM64T)으로 소개되었지만, 지금은 X64로 보통
부른다. IA32를 64-bit을 지원하기위해 확장한 것으로, IA32와 완전한 호환을 가지는 Compatibity mode와
64-bit mode를 지원한다. 우리가 흔히 말하는 64-bit 모드이다.
- 64-bit mode에서는 명령어에 8-bit REX prefix를 붙여서, 64-bit 레지스터를 사용할 수 있다. 또한, 64-bit mode에서는 레지스터 개수도 기존의 8개에서 16개로 다음과 같이 늘어났다.
- Long mode - Compatibility mode: eax, edx, exc, ebx, esi, edi, esp, ebp
- Long mode - 64-bit mode: rax, rdx, rxc, rbx, rsi, rdi, rsp, rbp, r8,r9,r10,r11,r12,r13,r14,r15
- AMD64에서는 Operating mode로서 총 5개가 지원된다.
- Long mode - Compatibility mode
- Long mode - 64-bit mode
- Legacy mode - Protected mode
- Legacy mode - Virtual 8086 mode
- Legacy mode - Real mode
- AMD64의 어드레스는 레지스터 값은 64bit으로 부호확장되어 보이며, 현재는 다음과 같은 범위를 가진다.
- physical address: 1TB (40-bit)
- virtual address: 256TB (48-bit) : 부호확장이 되었으므로, 유효한 virtual address는 다음 두 영역으로 된다.
- 0x0 ~ 0x00007FFF_FFFFFFFF
- 0xFFFF8000_00000000 ~ 0xFFFFFFFF_FFFFFFFF
Windows® Server 2003 R2 Platform SDK 설치목록(2006-03-15)
설치폴더
C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2
2005제거시 맨마지막에 뜨는 정리하라는 메세지!!
혹시라도 VS가 이상해서 다시 설치할경우.. 삭제시 정리해야될 요소를 안내하는 창이다.
제거되었습니다.
다음 단계: 추가 구성 요소 제거
Visual Studio를 설치하는 동안 컴퓨터에 추가 구성 요소가 설치되었을 수 있습니다. 이러한 구성 요소는 [프로그램 추가/제거]를 사용하여 아래 나열된 순서대로 수동으로 제거해야 합니다.
참고: 이 구성 요소를 제거하면 해당 구성 요소를 사용하는 다른 응용 프로그램이 영향을 받을 수 있습니다.
Visual Studio에서 다음 구성 요소를 설치했을 수 있습니다.
Microsoft MSDN 2005 Express Edition Microsoft Visual Studio 2005 Tools for Office Runtime 언어 팩 Microsoft Visual Studio 2005 Tools for Office Runtime Microsoft Device Emulator 버전 1.0 Microsoft .NET Compact Framework 1.0 Microsoft .NET Compact Framework 2.0 Microsoft SQL Mobile 2005 개발 도구 Microsoft Visual J# 2.0 재배포 가능 패키지 Microsoft Visual J# 2.0 재배포 가능 패키지 언어 팩 Microsoft Document Explorer 2005 Microsoft Document Explorer 2005 언어 팩 Microsoft Data Access Components 2.8 SP1(Windows 2000 전용)
다음 구성 요소는 SQL Server Express에서 설치되었을 수 있으며 아래 나열된 순서대로 제거해야 합니다. 참고: SQL Express 인스턴스를 제거한 후 남겨진 사용자가 만든 데이터베이스는 이후에 새 인스턴스에 다시 연결할 수 있습니다.
Microsoft SQL Server 2005 Express CTP Microsoft SQL Server 2005 Express Tools CTP Microsoft SQL Server 설치 지원 파일 Microsoft SQL 기본 클라이언트 다음 구성 요소는 마지막에 제거해야 합니다.
MSXML 6.0 파서 및 SDK(32비트 전용) MSXML 6.0 파서 및 SDK x64(64비트 전용) Microsoft .NET Framework 2.0 언어 팩 Microsoft .NET Framework 2.0
Feature Pack은 2008 sp1부터 추가된 BCGSoft의 MFC확장 라이브러리이다.
office2007의 Ribbon UI가 포함되어 있어 출시전부터 기존 mfc코드처럼 office의 소스도 볼수 있는거 아닌가 하는 개발자들의 기대와는 다르게 상용 라이브러리를 사서 MFC에 확장형식으로 넣어버렸다. (당근 소스까지)
기존 MFC 사용라이브러리중에 CodeJock의 XTP를 더 선호하는 사람이 많아서 그런지 아쉬워 하는 사람도 많은 것 같다.
상용이 공짜가 됐다는 거에 일단 무조건 떙큐~!
M$도 욕좀 먹었나보다. 그래서 라이브러리들을 추가한건 좋은데 sp1에 추가된 Feature Pack이나 TR1이 전부 외부에서 사온거라고 하니 역시 눈가리고 아웅인가? ㅡ.ㅡ; 어쨌든 그래도 필자는 반갑다.
2. 준비
sp1을 먼저 깔고 프로젝트 생성시 _BIND_TO_CURRENT_VCLIBS_VERSION를 전처리기에 선언하면 sp1라이브러리를 사용하게 된다. 당연히 배포할때는 2008 sp1용 재배포패키지로 배포해야된다.
_AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;
if (pState->m_pmapSocketHandle == NULL)
pState->m_pmapSocketHandle = new CMapPtrToPtr;
if (pState->m_pmapDeadSockets == NULL)
pState->m_pmapDeadSockets = new CMapPtrToPtr;
if (pState->m_plistSocketNotifications == NULL)
pState->m_plistSocketNotifications = new CPtrList;