1. 에러 리턴코드 맨 처음 에러를 감지한 함수에서 특정한 에러 코드를 리턴하게 하는 방법


2. 예외 처리

에러처리 함수를 사용하려면 콜스택을 거슬러 내려가서 에러처리 함수까지 가야할수도 있다.

SEH(Structured Exception Handling)  위와 같은 일을 하지 않고 에러를 전달한다.

에러가 발생하면 예외 객차라는 자료 구조에 정보를 넣고 콜 스택을 자동으로 펼쳐 try - catch 블록을 찾았을 경우 예외 객체를 처리할 수있는 catch를 찾고 스택이 펼쳐지면서 자동 변수들의 파괴자는 자동으로 호출된다.


하지만 SEH는 프로그램에 많은 부담을 주므로 게임에선 사용하기 힘들다.


3. Assert

GPG에 비슷한 내용이 있다.

'게임 엔진 아키텍처 > 3장 엔지니어링 기초' 카테고리의 다른 글

객체 메모리  (0) 2016.05.24
C/C++ 메모리 구조  (1) 2016.05.24
선언, 정의, 연결성  (0) 2016.05.24
멀티바이트 데이터와 엔디언  (1) 2016.05.24
수의 표현  (0) 2016.05.24
posted by 알쿠미

클래스 정적멤버


static 키워드란?

* 파일 범위에서 사용하면 변수가 다른 cpp에서 보이지 않고 사용되지 못하게 하고 오직 그 cpp에서만 보이게 된다.


* 함수 범위에서 사용하면 변수가 전역 변수이고 자동 변수가 아니지만 그 함수안에서만 보이게 한다.


* 구조체와 클래스 선언에서 사용하면 변수가 보통 멤버 변수가 아니라 전역 변수처럼 동작한다.


클래스에서 쓰인 static 키워드는 변수의 보이는 범위를 지정하지는 않는다.

대신 일반적인 멤버 변수처럼 각 인스턴스마다 존재할지, 아니면 클래스에만 존재해서 전역 변수 처럼 쓰일지 지정한다.


보이는 범위는 public, protected, private 키워드를 통해 결정된다.

클래스 전역변수는 클래스 네임스페이스에 포함되기 때문에 클래스 이름을 함께 사용해야 한다.

클래스 정적 변수를 위한 메모리는 반드시 cpp파일에 정의돼야 한다.


F32 Foo::sClassStatic = -1.0f; // 이런식으로 메모리 할당



1. 메모리 상의 객체 구조

struct Foo

{

U32 mUnsignedvalue;

F32 mFloatValue;

bool mSignedValue;

};


 +0x0

 mUnsignedvalue

 +0x4

 mFloatValue

 +0x8

 mBlooleanValue


2. 메모리 정렬과 패킹

1. 바이트 정렬 객체는 어떤 메모리 주소에도 올 수 있다.

2. 2바이트 정렬 객체는 짝수인 주소에만 올 수 있다.

3. 4바이트 정렬 객체는 4의 배수가 되는 주소에만 올 수 있다.

4. 16바이트 정렬 객체는 16의 배수가 되는 주소에만 올 수 있다.


* 메모리 정렬이 중요한 이유는 메모리 정렬이 제대로 지켜진 데이터 블록만 읽고 쓸 수 있기 때문이다.


* 구조체 전체를 놓고 봤을 때는 멤버의 정렬 조건중 가장 큰 것이 그 구조체의 정렬 조건이 된다. 남는 메모리는 컴파일러가 패딩으로 채운다.


3. C++ 클래스의 메모리 구조

+0x0

+sizeof(A)

메모리 구조 관점에서 보면 C++클래스는 상속과 가상 함수 때문에 메모리가 더 붙는다. 각 클래스 사이에도 메모리 정렬조건 때문에 패딩이 들어갈 수 있다.


가상함수가 있다면 가상함수테이블을 가리키는 vptr포인터 4바이트가 추가되고

이 vtable은 이 클래스가 선언하거나 상속하는 모든 가상 함수를 가리키는 포인터를 갖고 있다.





'게임 엔진 아키텍처 > 3장 엔지니어링 기초' 카테고리의 다른 글

에러감지와 처리  (0) 2016.05.24
C/C++ 메모리 구조  (1) 2016.05.24
선언, 정의, 연결성  (0) 2016.05.24
멀티바이트 데이터와 엔디언  (1) 2016.05.24
수의 표현  (0) 2016.05.24
posted by 알쿠미

1. 실행파일 이미지

C/C++ 프로그램은 링커가 실행 파일을 만들면서 완성된다.


1. 텍스트 세그먼트

  - 코드 세그먼트라고 불린다. 프로그램에서 정의한 모든 함수의 기계어를 담고 있다.


2. 데이터 세그먼트 

  - 초기 값을 가진 전역 및 정적 변수가 자리한다.

  - 이 형태대로 프로그램이 실행 될 때 메모리에 배치되고 값들은 지정한 대로 초기화 돼있다. 따라서 실행 파일이 메모리에 로드될 때 전역변수와 정적 변수는 바로 사용할 수있다.


3. BSS 세그먼트 (block started by symbol)

  - 초기화 되지 않은 모든 전역변수와 정적변수가 자리한다.

  - C/C++에서는 초기화 되지 않은 전역변수와 정적변수가 0으로 초기화 되는데 몇개가 될지 모르는 0의 값들을 무작정 들고 있기 보다는 링커는 얼마나 많은 마이트의 0이 있는지만 기록한다.

  - 운영체제는 실행 파일이 메모리에 로드돼 시작점이 불리기 직전에 이 값을 보고 공간을 할당하고 0으로 채운다.


4. 읽기 전용 데이터 세그먼트

  - 읽기 전용(constant)인 전역 데이터가 자리한다. 부동 소수인 상수나, const 키워드로 정의된 전역 인스턴스 등이 여기에 해당한다.

  - 정수 타입인 상수는 매니페스트 상수처럼 취급돼 사용되는 기계어 코드위치에 직접 삽입되는 경우가 대부분이다.


5. 프로그램 스택

  - 프로그램이 메모리에 로드될 때 운영체제는 프로그램 스택이라는 메모리 공간을 마련한다.

  - 스택 프레임에는 세가지 종류가 저장된다.

   ⓐ 리턴주소 - 해당 함수를 호출한 곳(호출한 함수)의 주소인데, 이 함수가 리턴한 후 다음 실행될 프로그램 위치다.

   ⓑ CPU 레지스터 - 함수가 호출되기 이전의 레지스터 값들을 스택에 저장함으로써 함수는 이전의 상태를 훼손할 염려없이 레지스터를 자유롭게 사용할 수 있다.

   ⓒ 지역 변수 - 호출된 함수의 지역 변수들은 스택에 자리한다.


6. 동적 할당 힙

 동적으로 할당된 메모리는 힙에 올라간다. 6장에서 좀더 자세하게 다룬다.

'게임 엔진 아키텍처 > 3장 엔지니어링 기초' 카테고리의 다른 글

에러감지와 처리  (0) 2016.05.24
객체 메모리  (0) 2016.05.24
선언, 정의, 연결성  (0) 2016.05.24
멀티바이트 데이터와 엔디언  (1) 2016.05.24
수의 표현  (0) 2016.05.24
posted by 알쿠미

1. 번역단위 살펴보기

컴파일러는 한번에 한개의 번역 단위만 처리하기 때문에 외부의 전역 변수나 함수를 처리할 때면 그냥 이런 외부참조들이 있을 것이라고 가정하고 진행할 수 밖에 없다.

이 결과 나온 목적파일들을 링커가 미확정 상태인 참조가 진짜 어떤 것인지 알아내려고 시도하고 이 과정이 성공하면 모든 함수와 전역변수, 정적변수, 번역 단위 간 참조가 전부 포함된 실행 파일이 만들어진다.


2. 선언과 정의의 차이

 C/C++ 에서느 변수나 함수를 사용하기 전에 반드시 선언되고, 정의 돼야 한다.

* 선언 데이터 객체나 함수의 형태를 나타낸다.

 - 컴파일러에 '이름'과 데이터 타입 혹은 함수의 서명을 알려 준다.


* 정의 프로그램 안에 고유한 저장 공간을 나타낸다. 이 저장 공간 안에는 변수, 구조체 및 클래스의 인스턴스, 함수의 기계어 등이 들어갈 수 있다.


3. 선언과 정의의 중복 

선언은 여러번 할 수 있지만 정의는 한번 밖에 할 수 없다.

한 번역 단위 안에서 같은 정의가 여러번 나오면 컴파일러가 에러를 낸다.

똑같은 정의가 서로 다른 번역 단위에 있다면 컴파일러는 알아채지 못한다.

이때는 링커가 중복된 심볼 에러를 낸다.


4. 연결성

외부 연결성은 다른 번역 단위에서도 볼수 있고 사용할 수 있다.

내부 연결성은 정의가 위치한 번역 단위에서만 볼 수 있기때문에 그 번역 단위에서만 쓸 수 있다.


기본적으로 모든 정의 는 외부 연결성 이며, static키워드는 정의를 내부 연결성으로 부꿀 때 사용한다. .cpp마다 똑같은 정의가 있더라도 static이 붙어있으면 링커는 이것을 서로 다른 존재라호 인식한다.


인라인 함수는 기본적으로 내부 연결성이다.

'게임 엔진 아키텍처 > 3장 엔지니어링 기초' 카테고리의 다른 글

객체 메모리  (0) 2016.05.24
C/C++ 메모리 구조  (1) 2016.05.24
멀티바이트 데이터와 엔디언  (1) 2016.05.24
수의 표현  (0) 2016.05.24
C++ 개념과 사용법  (0) 2016.05.23
posted by 알쿠미

1바이트보다 큰 값들을 멀티바이트 값이라고 한다.

LSB( least significant byte) 최하위 바이트

MSB( most significant byte) 최상위 바이트

* 리틀 엔디언

  - LSB가 MSB보다 낮은 메모리 주소에 저장되는 방법

ex) 0xABCD1234 라면 0x34, 0x12, 0xCD, 0xAB로 순으로 저장됨

* 빅 엔디언

  - MSB가 LSB보다 낮은 메모리 주소에 저장되는 방법

ex) 0xABCD1234 라면 0xAB, 0xCD, 0x12, 0x34로 순으로 저장됨


엔디언 문제를 해결하는 방법

1. 모든 데이터 파일을 텍스트 형태로 저장하고 멀티바이트 숫자는 한 숫자가 한 바이트가 되게 십진수 형태로 저장한다.

2. 툴에서 디스크에 저장하기 직전에 엔디언을 바꾸게 하는 방법
PC가 게임을 돌릴 콘솔과 엔디언이 달라도 무조건 콘솔의 엔디언을 따르게 하는 방법


엔디언을 바꾸는 함수

inline U16 swapU16(U16 value)

{

return ((value & 0x00FF << 8) | ((value & 0xFF00) >> 8);

}


inline U32 swapU32 ( U32 value)

{

return    ((value & 0x000000FF) << 24)

((value & 0x0000FF00) << 8)

((value & 0x00FF0000) >> 8)

((value & 0xFF000000) >> 24)

}



'게임 엔진 아키텍처 > 3장 엔지니어링 기초' 카테고리의 다른 글

객체 메모리  (0) 2016.05.24
C/C++ 메모리 구조  (1) 2016.05.24
선언, 정의, 연결성  (0) 2016.05.24
수의 표현  (0) 2016.05.24
C++ 개념과 사용법  (0) 2016.05.23
posted by 알쿠미

수의 표현

1. 수 표현

  ⓐ 수의 기초

    - 2진 법은 0b를 앞에 붙여 사용하기도 한다. 오른쪽 부터 왼쪽으로 갈수록 1씩 증가하는 2의 제곱이다.

  ⓑ 16진법은 0x로 시작하며 컴퓨터가 데이터를 저장 할 때는 한 바이트(8비트)단위로 저장하므로, 16진수 하나가 정확히 4비트를 표현할 수 있기때문에 16진수 2개로 한바이트를 표현할 수 있다.

ex) 0xFF = 0b11111111 = 255;

     0xB052 = 45,138;


2. 부호 있는 정수와 부호 없는 정수

  ⓐ 부호 없는 32비트 정수를 나타내려면  0x00000000부터 0xFFFFFFFF(4,294,967,295)까지가 된다.


  ⓑ 부호 있는 32비트 정수를 나타내려면 2의 보수를 사용한다.

    - 0xFFFFFFFF이 -1을 나타내고 음수는 여기서 하나씩 감소하며 나타낸다. 최상위 비트가 1인 수는 음수다.

    - 0x00000000부터 0x7FFFFFFF까지 양의 정수이고 0x80000000부터 0xFFFFFFFF까지 음의 정수다.


2의 보수란 어떤 수를 커다란 2의 제곱수에서 빼서 얻은 이진수이다. 


2. 고정소수점 표현법

  ⓐ 정수부를 표현할 비트와 소수부를 표현할 비트의 수를 임의로 고정한다.

    - 정수부는 1씩 증가하는 2의 제곱을 나타내고 소수부는 1씩 증가하는 2의 제곱의 역을 나타낸다.

(큰수를 표현하기에 무리가 있다. 그래서 부동소수점을 사용한다.)


3. 부동 소수점 표현법

  ⓐ 정소와 소수를 합친수인 가수와 가수 안에서 어디에 소수점이 위치할지를 나타내는 지수, 그리고 부호비트 이렇게 세부분으로 나뉜다.

  ⓑ 표준은 IEEE-754 이고 가장 높은 비트를 부호비트로 사용하고 그 다음 8비트는 지수로, 나머지 23비트를 가수로 사용할 것을 명시한다.

  * v = s * 2^(e-127) * (1+m); 


3. 절댓값과 정확도 간의 균형

  ⓐ 부동소수의 정확도는 절댓값이 작을수록 높아진다. ( 한정도니 비트로 표현된 가수를 정수부와 소수부가 나눠써야하기 때문에.) - 유효자릿수


  ⓑ 머신 엡실론은 2^(-23) 이고 대력 1.192* 10^(-7) 이다. 이보다 작은 값은 표현할 수 없다.


4. 기본적인 데이터 타입

  ⓐ char 보통 8비트 ASCII나 UTF-8 부호를 전부 담을 수 있을 정도의 크기

  ⓑ int, short, long - int 는 대상 플랫폼에서 제일 효율적으로 처리할 수 있는 크기의 부호있는 정수 타입이다.

(short는 int보다 작은 수를 담고 보통 16비트를 쓴다. long은 int와 같더나 크고 32나 64비트를 쓴다.)

  ⓓ float 오늘날 대부분 컴파일러에서 32비트 IEEE-754 부동소수를 사용한다.

  ⓔ double 2배 정밀도(64비트) IEEE-754 부동소수

  ⓕ bool 1비트로는 구현하지 않으며 8비트나 32비트 전부쓰는 컴파일러도 있다.


5. 컴파일러에 따라 크기가 다른 타입

 __int8, __int16, __int32, __int64 와 같은 타입이 있다.


6. SIMD (Single Instruction Multiple Data)

 여러개의 데이터를 병렬적으로 동시에 연산하는 기능 (콘솔에서 많이 사용)




'게임 엔진 아키텍처 > 3장 엔지니어링 기초' 카테고리의 다른 글

객체 메모리  (0) 2016.05.24
C/C++ 메모리 구조  (1) 2016.05.24
선언, 정의, 연결성  (0) 2016.05.24
멀티바이트 데이터와 엔디언  (1) 2016.05.24
C++ 개념과 사용법  (0) 2016.05.23
posted by 알쿠미

1. 클래스의 특성

* 캡슐화 - 객체가 정해진 인터페이스만 공개하고 객체 내부의 상태와 상세한 구현 사항을 숨기는 것을 캡슐화라고 한다.


* 상속 - 어떤 클래스가 이미 존재하는 클래스를 확장하는 것을 상속한다고 말한다.

(상속은 두 클래스 사이에 is-a 관계를 말한다.)


* 다형성(폴리모피즘)

 - 프로그래밍 언어에서 서로 다른 타입의 객체들을 하나의 공통 인터페이스로 다룰 수 있는 기능이다.


* 합성과 집합

 - 상속만 사용할 것이 아니라 클래스 간의 관계를 has-a, uses-a 관계를 형성해서 복잡한 상속 관계를 만들지 않고 문제를 해결하는 것이 좋다.


* 디자인 패턴

(GOF를 보고 정리하자..)


2. 코딩규칙

* 인터페이스를 중시할 것 - 간결하고 단순하며 최소한의 것만 포함해야 한다

(이해하기 쉽고, 주석을 잘 달아야한다.)


* 이름을 잘 지을 것 클래스나 함수, 변수의 목적에 맞는 가장 직관적인 이름을 지어야 한다.


* 전역 네임스페이스를 깔끔하게 유지할 것

  - 네임스페이스나 이름에 붙이는 접두사 등을 사용해 이름이 다른 라이브러리의 이름과 충돌하지 않게 해야 한다.

#define문을 이용해 이름을 정의하는데 주의가 필요하다.

(C++ 전처리기는 단순히 텍스트를 바꿔 칠 뿐이라서 C/C++의 범위나 네임스페이스를 깡그리 무시하기 때문이다.)


* 널리 알려진 C++ 사용법을 따를 것


* 코딩규칙은 일관되야 한다.

  - 코드를 처음부터 짠다면 일관된 규칙을 두고 짜고, 코드를 고친다면 코드의 규칙을 지켜가면서 수정하자.


* 오류를 스스로 드러내는 코드를 작성하라

  - 흔히 저지를 수 있는 프로그래밍 오류를 쉽게 볼 수 있도록 해주는 코드가 좋은 코드이다.




'게임 엔진 아키텍처 > 3장 엔지니어링 기초' 카테고리의 다른 글

객체 메모리  (0) 2016.05.24
C/C++ 메모리 구조  (1) 2016.05.24
선언, 정의, 연결성  (0) 2016.05.24
멀티바이트 데이터와 엔디언  (1) 2016.05.24
수의 표현  (0) 2016.05.24
posted by 알쿠미