III : 64비트 기반 프로그래밍
뇌를 자극하는 윈도우즈 시스템 프로그래밍 을 읽고 정리한 문서입니다 ;)
WIN32 vs WIN64
시스템이 어떤 비트 환경에서 동작하는지 구분하는 것은 두 가지로 판별할 수 있는데, 하나는 한 번에 전송 및 수신할 수 있는 데이터의 크기이고, 이는 즉 IO 버스의 대역폭을 의미한다.
또한, CPU가 데이터를 처리함에 있어 한 번에 처리 가능한 데이터의 크기가 비트 판별의 기준이 된다.
32비트 환경에서는 주소값의 표현을 가장 효율적인 32비트로 하였기에 최대 4GB의 메모리를 가질 수 있는 시스템이 되었고, 64비트 환경에서는 64비트로 메모리를 표현하기에 최대 16EB의 메모리를 가질 수 있는 시스템이다.
프로그램 구현 관점에서의 WIN32 vs WIN64
마이크로소프트는 64비트 기반의 운영체제를 내놓으면서 프로그래밍 스타일에 대한 가이드를 제공하고 있기에, 이에 따르는 것이 64비트 기반 프로그래밍의 첫걸음이다.
윈도우는 LLP64 데이터 표현 모델을 따르기에, long long
형과 pointer
형이 64비트이다. 이는 LP64를 쓰기에 long
, long long
, pointer
형을 쓰는 유닉스와는 long
자료형의 크기가 차이가 난다.
이에 따라 가장 첫 번째로 유의해야 할 점이 생기는데, 다음 코드를 보자.
int arr[10] = {0,};
int arrAddress = (int)arr;
printf("array address : %d", arrAddress);
위 코드는 32비트 환경에서는 전혀 문제 없지만, 64비트 환경에서는 메모리 주소 (8바이트)를 int
형 데이터 공간에 넣게 되어 데이터 손실이 발생한다.
따라서, 64비트 시스템에서는 포인터가 가지고 있는 주소값을 다른 형으로 저장할 때 주의하자.
윈도우 프로그래밍에 사용되는 자료형은 기본 자료형을 명칭을 바꾸고 조금 더 확실히 하여 사용한다.
윈도우 자료형 | 의미 | 정의 형태 |
---|---|---|
BOOL | Boolean Value | typedef int BOOL |
DWORD | 32bit unsigned integer | typedef unsigned long DWORD |
DWORD32 | 32bit unsigned integer | typedef unsigned int DWORD32 |
DWORD64 | 64bit unsigned integer | typedef unsigned __int64 DWORD64 |
INT | 32bit signed integer | typedef int INT |
INT32 | 32bit signed integer | typedef signed int INT32 |
INT64 | 64bit signed integer | typedef signed __int64 INT64 |
UINT | 32bit unsigned integer | typedef unsigned int UINT |
PINT | INT32에 대한 포인터 | typedef int* PINT |
PLONG | LONG에 대한 포인터 | typedef LONG* PLONG |
이처럼 윈도우 프로그래밍에는 DWORD
, INT
, LONG
과 같은 자료형이 많이 사용되며, 64비트가 되며 기존 자료형 뒤에 32, 64가 붙은 것은 기존 시스템을 유지하며 명확성을 줄 수 있기 위함이다.
마이크로소프트는 또한 Polymorphic 자료형을 정의하고 있는데, 이는 다양한 모습을 가지는 자료형으로서, 환경에 따라, 즉 32비트, 64비트에 따라 다르게 정의되는 자료형이다. 이를 통해 32비트와 64 비트 간 호환성을 높일 수 있다.
대표적으로 LONG_PTR
, INT_PTR
등이 존재하는데, 이는 비트 환경에 따라 포인터의 크기가 다른 것을 아래 예시처럼 다형 자료형으로 쉽게 처리할 수 있게 해준다.
UINT_PTR CalDistance(UINT_PTR a, UINT_PTR b) {
return a-b;
}
...
_tprintf(_T("distance : %d"), CalDistance((UINT_PTR)&val1, (UINT_PTR)&val2));
...
오류의 확인
오류가 발생하는 것은 전혀 이상한 것이 아니다. 다만 그에 따라 오류의 원인을 파악하고 문제를 해결할 수 있어야 한다.
윈도우 시스템 함수를 호출하는 과정에서 문제가 생기면, **GetLastError()
함수 호출**을 통해 오류의 원인을 알 수 있다. 많은 수의 윈도우 시스템 함수는 오류가 발생했을 때 NULL을 리턴한다.
윈도우 시스템 함수가 호출될 때마다 GetLastError
함수가 반환하는 에러 코드는 갱신되기 때문에, 오류 발생 직후에 바로 코드 확인 및 알맞을 처리를 해야 한다.
이것만은 알고 갑시다
- 64비트 시스템과 32비트 시스템의 구조적 차이
- 한 번에 송수신할 수 있는 데이터 크기와, 한 번에 처리할 수 있는 데이터 크기
- 주소값 표현에 사용되는 바이트 수가 지니는 의미
- 주소를 표현하는데 64비트 시스템은 32비트가 아닌 64비트를 사용하므로, 프로그래머가 표현할 수 있는 값의 범위가 늘어났다.
- Polymorphic 자료형
- 환경에 따라 다른 의미를 가짐으로서 더욱 유연한 프로그래밍을 가능하게 해준다.
- LLP64와 LP64
- 윈도우에서는 LLP64를 사용하고, 유닉스에서는 LP64를 사용하므로,
long
이 가지는 크기에 차이가 존재한다.
- 윈도우에서는 LLP64를 사용하고, 유닉스에서는 LP64를 사용하므로,
GetLastError
함수의 사용방법- 윈도우 시스템 함수가 정상 코드를 리턴하지 않았다면, 바로
GetLastError
함수 호출을 통해 오류를 확인하자
- 윈도우 시스템 함수가 정상 코드를 리턴하지 않았다면, 바로
'공부한 이야기 > 윈도우 OS' 카테고리의 다른 글
V : 프로세스의 생성과 소멸 (0) | 2023.04.29 |
---|---|
IV : 컴퓨터 구조에 대한 두번째 이야기 (0) | 2023.04.29 |
II : 아스키코드 VS 유니코드 (0) | 2023.04.29 |
I : 컴퓨터 구조에 대한 첫번째 이야기 (0) | 2023.04.29 |
프로세스 기초 (0) | 2022.08.12 |