Create TOC

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

2013년 6월 27일

C++/Visual Studio의 Code Analysis에서 strsafe.h에 대해 경고를 출력하지 않게 설정

Visual Studio의 Code AnalysisDetecting and Correcting C/C++ Code Defects로 소스를 점검하다 보면 strsafe.h에 대해 많은 양의 경고를 출력한다. strsafe.h를 포함하기 전에 warning 설정을 바꿔주면 경고가 나오지 않는다.

#include <CodeAnalysis/warnings.h>
#pragma warning(push)
#pragma warning(disable: ALL_CODE_ANALYSIS_WARNINGS)
#include <strsafe.h>
#pragma warning(pop)

2008년 9월 20일

error LNK2005

MFC 와 runtime library의 링크 순서가 잘못될 경우 아래와 같은 메시지를 볼 수 있습니다.

mfc42u.lib(dllmodul.obj):error LNK2005: _DllMain@12 already defined in MSVCRT. lib(dllmain.obj)

해결책은 아래와 같습니다. (VC6 기준)

  1. Project 메뉴에서 Settings를 누릅니다.
  2. Project Settings 대화 상자의 Settings For 에서 링크 오류가 발생하는 프로젝트 구성을 선택합니다.
  3. Link 탭의 Category 콤보 상자에서 Input을 선택합니다.
  4. Ignore libraries 상자에 msvcrt.lib 를 삽입합니다.
  5. Object/library modules 상자에 라이브러리 mfcs42u.lib msvcrt.lib 를 삽입합니다.

http://support.microsoft.com/kb/148652

2003년 3월 8일

wide character (wchar_t)

wchar_t

wide character란 1바이트가 아닌 그 이상의 바이트를 차지하는 정수에 저장되는 문자 코드를 의미한다. 즉 유니코드를 말한다.

C 표준은 wide character를 표현하기 위해 wchar_t 데이터 형을 정의하고 있다. 그러나 표준에서 정확한 형식을 정의하지 않은 이유로 컴파일러 구현마다 정의가 다르다.

MSVC 경우 unsigned short를 사용한다. 즉 UCS-2를 나타낸다.(UTF-16과는 다르다고 한다.). MSVC 경우 Unicode API에서는 WCHAR를 사용하는데 정의 상 wchar_t와 동일하다.(unsigned short)

gcc 경우에는 int를 사용하며 UCS-4를 나타낸다. MSVC와 동일하게 사용하려면 -fshort-wchar 옵션을 주면 된다. 그러나 이렇게 변경했을 경우 C 표준 라이브러리들이 제대로 동작할지는 알 수 없다.

이런 모호한 이유로 wchar_t를 사용할 때는 해당 시스템의 매뉴얼(msdn이던 man page던)을 읽고 사용하는 수밖에는 없다.

wint_t

char을 위한 wchar_t가 있다면 int를 위한 wint_t가 있다.

C 표준 라이브러리를 보면 문자를 다루는 함수들은 char 대신 int를 사용한다(이유를 알고 있었는데 잊었다).

이런 함수들의 unicode 버전은 wint_t를 사용한다.

주의할 점은 ansi 세계에서 문자열 표현을 위해서 int 배열을 쓰지 않는 것처럼 unicode 세계에서도 문자열 표현을 위해서 wint_t를 사용하지 않는다는 점이다(wchar_t를 사용한다).

unicode string literal

C 표준에서 unicode string literal은 아래와 같은 방법으로 표현하도록 정의되어 있다.

wchar_t wtext[] = L"Hello";

그런데 이때 gcc와 MSVC의 동작이 다르다. MSVC는 시스템 기본 로케일을 기준으로 UCS-2로 변환하지만(즉 컴파일하는 시점의 시스템 설정에 따라 다르다), gcc 경우 소스 파일의 각 byte를 하나씩 wchar_t에 복사하고 있다. 즉 소스가 영문 ascii라고 전제하고 UTF-32로 변환한다.

2002년 8월 20일

Visual C++ 6.0 버그

variable scope 버그

c++ spec을 지키지 않습니다.

for (int i = 0; i < 10; i++)
{
	; // nop
}

cout << i << endl;

이런 코드가 있을때 c++ spec 상 변수 ifor 범위 안에서만 유효해야 합니다. 따라서 cout 부분에서 에러가 발생해야 합니다.
하지만 VC 에서는 선언된 이후 계속 유효한 상태로 남아있습니다.

이 때문에 코드 이식성을 높이기 위해 위와 같은 문법을 사용할 수 없습니다.

기본 최적화에 따른 부동 소수점 연산 오류

아래 내용은 sleek에서 논의되었던 내용을 정리한것임.


다음과 같은 소스가 있습니다.

#include <stdio.h>

int main(int argc, char* argv[])
{
	float a = 0.433f;
	float b = a*1000.0f;
	int c = (int)b;

	printf("value %d \n",c);
	return 0;
}

이것을 실행해보면 432 가 나옵니다(VC++ 6.0 SP3, 4, 5 에서 확인함. gcc 에서는 433으로 잘 나옴).

반면

c = (int)(0.433 * 1000.0);

로 바꾸면 433으로 잘 나옵니다.

그리고 위의 소스를 다음과 같이 바꾸어도 433 이 잘 나옵니다.

#include <stdio.h>

int main(int argc, char* argv[])
{
	float a = 0.433f;
	float b = a*1000;

	float temp = 0.0f; // 쓸데없는 변수
	temp /= 100.0f;    // 쓸데없는 연산

	int c = (int)b;


	printf("value %d \
",c);
	return 0;
}

이렇게 되는 이유가 FPU 오차에 최적화 문제가 겹쳐서 발생되는 문제입니다.

float a = 0.433f;
float b = a*1000;
int c = (int)b;

여기서 a*1000는 FPU 레지스터에는 4.32999...e+0002 로 값이 나오는데, 이게 실제 메모리 b로 가면 4.33300..e+0002으로 라운딩이 됩니다.

근데.. 다음줄 c=(int)b;를 계산하려고 보니 b의 값이 아직 레지스터에 남아 있으니 4.3299...e+0002 를 가져다 계산하고 (int)변환은 라운딩 없이 무조건 잘라버리니까 결과는 432가 나오는데.. 즉 이건 c=(int)(a*1000); 과 동일한 값이 됩니다.

하지만 c=(int)b; 를 계산하기 전에 다른 코드가 있다면, 레지스터에 b를 다시 로드해야 되므로 메모리 b에 저장된 4.333000..e+0002를 먼저 FPU 레지스터에 불러들이고, 결과는 433이 나오게 됩니다.

정리해보면..

float a = 0.433f;
float b = a*1000;
int c = (int)b; // 이건 432
c= (int)b; // 이건 433
c= (int)(a*1000); // 이건 432
c= (int)b; // 이건 433

결국 Register에 있는 내용과 실제 메모리에 있는 내용이 다르면 당연히 메모리에 있는걸 읽어 와야 되는데 VC의 옵티마이저가 이걸 잘못 생각해서 errornous한 code 라고 생각하는 것 같습니다.

결국 MSDN 에 /Op 옵션을 사용하라고 나와있습니다.

PRB: Use /Op to Avoid Loss of Precision from Optimization

ps) VC.NET 에서는 이런 문제가 발생하지 않습니다 :)

Class view의 버그

아래 코드를 입력하고 class view 에서 확인해 보면 몇몇 함수는 제대로 표시되지 못합니다.

void a(int a, int b, int c);
void b(int a, int b = 1, int c = 1);
void c(int a, int b = 1, BOOL c = 1);
void d(int a, BOOL b = 1, BOOL c = 1);
void e(int a, BOOL b = 1, HKEY c = 1);