int main()
{
unsigned int X1 = 1234567;
unsigned int X2 = 1234567;
unsigned int X3 = X1 * X2;
std::cout << "X3 = " << X3 << std::endl;
unsigned __int64 BigX1 = 1234567;
unsigned __int64 BigX2 = 1234567;
unsigned __int64 BigX3 = BigX1 * BigX2;
std::cout << "BigX3 = " << BigX3 << std::endl;
getchar();
return 0;
}
<코드1>를 실행하면 변수 X3와 BigX3의 값이 서로 같을까요? 혹시 같다고 생각하시는 분들은 unsigned int의 최대 값이 얼마인지 MSDN에서 검색해 보세요... 네 결과는 서로 다릅니다. 둘 다 계산에 사용하는 값은 같지만 결과가 다르게 나오는 이유는 unsigned int로는 X1과 X2를 곱해서 나온 값을 보관할 수 없기 때문입니다. X3 = X1 * X2에서 X3는 오버플로우가 발생하여 상위 비트가 삭제되어 올바른 계산 값이 저장되지 않습니다.
<코드 1의 결과>
<코드 1>의 코드는 사실 별로 길지 않은 코드이기 때문에 실행하기 전에 오버플로우가 발생하리라는 것을 충분히 예상할 수 있고, 혹은 실행 후에 X3의 값이 예상하지 못한 값이 들어가 있어도 문제를 쉽게 파악할 수 있을 것입니다. 그러나 우리가 만드는 애플리케이션은 복잡하고 긴 코드를 가지고 있습니다. <코드 1>과 같은 오버플로우에 의해서 버그가 발생하면 쉽게 버그를 찾기 힘들고 특히 오버플로우에 의해 애플리케이션이 오 동작하여 크래쉬가 발생할 수도 있습니다.
안전한 애플리케이션을 만들기 위해서는 안전한 코드를 만들어야 합니다. 보통 안전한 코드를 생각하면 포인터 조작과 문자열 조작을 주로 중요하게 다루고 VC++에서도 안전한 문자열 조작 위해 ‘_s’가 붙은 문자열 조작함수를 사용하도록 VC++에서 종용하고 있어서 요즘은 대 부분 이것을 사용하고 있습니다. 그러나 정수 계산에 대해서는 안전한 코드를 위해 지원해 주는 것이 없었습니다.
SafeInt 란?
VC++ 10에서는 안전한 정수 계산을 위해서 새로운 라이브러리를 지원해 줍니다. 이 라이브러리의 이름은 SafeInt 입니다. SafeInt는 C++의 템플릿으로 만들어서 char 형에서 __int64 형까지 8비트에서 64비트 사이의 크기를 가진 모든 정수 형을 사용할 수 있습니다.
SafeInt 라이브러리를 사용하면 결과를 담을 변수의 형 보다 큰 정수 값 연산을 하거나 0으로 나누기 연산을 할 때 발생하는 오버플로우를 감지 할 수 있습니다.
SafeInt 사용
SafeInt를 사용하기 위해서는 헤더 파일 safeint.h 를 포함하고 msl::utilities 이름 공간을 선언해야 합니다.
< 코드 2 >
#include <safeint.h>
using namespace msl::utilities;
int main()
{
SafeInt<unsigned int> X1(1234567);
unsigned int x2 = 1234567;
SafeInt<unsigned
int> X2(x2);
SafeInt<unsigned int> X3 = X1 * X2;
getchar();
return 0;
}
<코드 2>를 디버그 모드에서 실행하면 아래와 같은 ASSERT 메시지가 발생합니다.
이유는 오버플로우가 발생했기 때문입니다. 그러나 릴리즈 모드에서는 ASSERT 메시지가 발생하지 않습니다. 다만 크래쉬가 발생합니다. -_-;;
오버플로우에 의해서 디버그 모드에서는 ASSERT 메시지, 릴리즈 모드에서는 크래쉬가 발생하는 이유는
에서 예외가 발생하기 됩니다. SafeInt를 사용하는 경우
오버플로우가 발생하면 예외를 발생시키기 때문에 try{} catch{}로 예외를 처리해 주지 않으면
안됩니다. 예외 처리가 올바르게 하면 오버플로우가 발생했을 때 발생하는 문제를 올바르게 대처하던가 어디에서 어떻게 오버플로우가 발생했는지 쉽게 알 수 있습니다.
그리고 SafeInt는 일반 정수형과 같이 연산을 할 수도 있다.
<코드 3>
#include <iostream>
#include <safeint.h>
using namespace msl::utilities;
int main()
{
SafeInt<unsigned int> X1(1234567);
unsigned int X2 = 123;
SafeInt<unsigned int> X3 = X1 * X2;
getchar();
return 0;
}
이번 회에는 간단하게 정수 연산 시의 오버플로우 문제와 SafeInt가
무엇인지, SafeInt의 간단한 사용 방법만 설명하였습니다.
다음 회는 <코드 2>에서 발생하는 예외를 어떻게 처리하는지 설명하겠습니다.
'Visual C++ 10' 카테고리의 다른 글
[SafeInt] C++에서 안전한 정수 연산을 하자 - 3 (5) | 2011.03.02 |
---|---|
[SafeInt] C++에서 안전한 정수 연산을 하자 - 2 (0) | 2011.02.22 |
VS2010 C++ 프로젝트의 디렉토리 설정 (2) | 2010.08.09 |
[Upgrade to VC++ 10] _WIN32_WINNT 버전 문제 (6) | 2010.08.02 |
Visual C++ 10의 변화 (0) | 2010.05.02 |