64비트 기반 프로그래밍

64비트 기반 프로그래밍

64비트 시스템을 고려한 프로그래밍으로 자료형에 대해서 고려해야 한다.


LLP64 vs LP64

32비트 시스템과의 호환성을 중시한 모델


운영체제 

모델 

char 

short 

int 

long 

포인터 

Windows 

LLP64  

1b yte 

2 byte 

4 byte 

4 byte 

8 byte 

UNIX 

LP64 

1 byte 

2 byte 

4 byte 

8 byte 

   8 byte    



Windows 에서는 LLP64 모델을, UNIX 계열에서는 LP64 모델을 채택하고있는데

32비트 시스템과의 호환성을 고려하여 기존과의 차이는 포인터에서만 볼 수있다.



64비트와 32비트 공존의 문제점

데이터 손실의 문제    


#include<stdio.h>

int main(void)

{

int arr[10]={0,};

int arrVal=(int)arr;

printf("pointer : %d \n ",arrVal);

return 0;

}


위 예제를 보면 arr이라는 배열의 주소값을 int형으로 강제형변환을 통하여 출력하려한다. 32비트 시스템이라면 포인터가 4byte이기때문에 문제가 발생하지 않을 것이다.

하지만 64비트 시스템이라면 arr 이 8byte 이고 int형은 4byte 이기때문에 문제가 발생 할수 있다. 

※64비트 시스템에서는 포인터를 기본자료형으로 변환하지말자!



Windows 스타일 자료형

Polymorphic 자료형

#if define(_WN64)

typedef __int64 LONG_PTR;

typedef unsigned __int64 ULONG_PTR;

typedef __int64 INT_PTR;    

typedef unsigned __int64 UNIT_PTR;


#else 

typedef long LONG_PTR;

typedef unsigned long ULONG_PTR;

typedef int INT_PTR;

typedef unsigned int UINT_PTR;


#endif


Polymorphic 자료형은   _WIN64 를 정의 했을때 다형적 자료형이 정의된다.

하나만 예로 들어  UNIT_PTR 은 64비트일때 unsigned __int64로  해석되고

32비트일때는 그냥  unsigned int로 해석된다.

PTR이 들어가서 포인터형으로 오해 할 수 있지 Polymorphic 자료형은 포인터 타입이 아니다.

PTR이 들어간 이유는 포인터 연산을 활용하기 위한 자료형일 뿐이다.

밑의 예제를 보자.




예제3-1]

UINT CalDistance(UINT a, UINT b)

{

return a-b;

}


int _tmain(void)

{

INT val1=10;

INT val2=20;

 _tprintf(_T("Position %d, %d \n"),

(UINT)&val1, (UINT)&val2);

_tprintf(_T("distance : %d \n"),

CalDistance((UINT)&val1,(UINT)&val2)

 

);

return 0;


}


예제를 보면 val1과 val2의 거리를 구하는 예제이다.

하지만 UINT 자료형은 4byte이다. 32비트시스템이면 몰라도 64비트시스템에서는 정상적으로 안될 수 있다.

이럴때 UINT 대신 UINT_PTR을 쓰면 32비트 일 때는 unsigned int 로

  64비트 일 때는  unsigned __int64로 

해석되어 문제가 발생하지 않고 메로리 낭비도 줄일 수 있다.

#if define(_WIN64)

typedef unsigned __int64 UNIT_PTR;

#else

typedef unsigned int UINT_PTR;

#endif



GetLastError 함수와 에러코드


함수호줄의 성공여부 확인의 기본

 GetLastError 함수 호출

windows시스템에서 오류가 발생 할 경우 전역 메모리공간에 오류의 이유가 저장이 된다. 그래서 여기서 가져와서 해석하면되는데 이 공간의 접근을 도와주는 함수가 GetLastError 함수이다.



Constant / value 

Description 

ERROR_ARITHMETIC_OVERFLOW
534 

 Arithmetic result exceeded 32 bits.

 ERROR_PIPE_CONNECTED

535

 There is a process on other end of the pipe.

 ERROR_PIPE_LISTENING
536

Waiting for a process to open the other end of the  pipe. 

ERROR_EA_ACCESS_DENIED

994 

 Access to the extended attribute was denied.

 ERROR_OPERATION_ABORTED

995

 The I/O operation has been aborted because of either a thread exit or an application request.

 ERROR_IO_INCOMPLETE
996

 Overlapped I/O event is not in a signaled state.

ERROR_IO_PENDING

997 

 Overlapped I/O operation is in progress.

 ERROR_NOACCESS

998

Invalid access to memory location. 

 ERROR_SWAPERROR

999

Error performing inpage operation. 


함수에서 반환되는 숫자로 오류를 알 수 있다.

MSDN에 가보면 더 많은 오류설명을 볼 수 있다.

실제 프로젝트에서 많이 쓰인다.




예제3-3]


int _tmain(void)

{

HANDLE hFile=

CreateFile(   //Windows system 함수.

_T("ABC.DAT"),GENERIC_READ,FILE_SHARE_READ,

NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,

NULL);

if(hFile==INVALID_HANDLE_VALUE)

{

_tprintf(_T("error code: %d\n"), GetLastError());


return 0;

}


return 0;                                           실행결과

}                                                     Error code: 2


CreateFile함수는 윈도우시스템함수이므로 크게 신경쓰지말자.

ABC.DAT 파일을 열려고 하는데 이런파일이 없다.  

그래서 오류가 발생했다는것을 알고 GetLastError 함수를 호출하면 에러 코드를 얻을 수 있다.


GetLastError 함수는 에러의 발생 이유를 확인하는 함수이지 에러가 발생했는지를 확인하는 함수는 아니다.

에러가 발생하면 그 원인이 전역공간에 저장된다고 하였는데 다른 함수가 호출되면 그 값이 변할 수 있다. 그렇기 때문에

에러가 발생이 됐는지 확인 이후 어느 함수보다 GetLastError 함수가 먼저 호출해야 정확한 에러이유를 정확히 알 수있다.



+ Recent posts