새로 생성한 스크립트
- Thread
- Static
- VirtualAlloc
- Macro
- Lambda
void Loop();
void MultiThread();
void MultiThread1();
void MultiThread2();
int main()
{
Loop();
return 0;
}
void Loop()
{
for (int i = 0; i < 100; i++)
{
printf("1 : %d\\n", i);
}
printf("반복 1 종료\\n");
for (int i = 0; i < 100; i++)
{
printf("2 : %d\\n", i);
}
printf("반복 2 종료\\n");
}
Thread
- C# 쓰레드와 다르게 바로 쓰레드를 실행할 수 있다.
void MultiThread1()
{
thread t(bind(MultiThread)); //C# 쓰레드와 다르게 바로 쓰레드를 실행할 수 있다.
}
- C#처럼 join()을 해야 쓰레드가 작동한다.
void Loop();
void MultiThread();
void MultiThread1(int number);
void Lambda();
int main()
{
Loop();
return 0;
}
void Loop()
{
for (int i = 0; i < 100; i++)
{
printf("1 : %d\\n", i);
}
printf("반복 1 종료\\n");
for (int i = 0; i < 100; i++)
{
printf("2 : %d\\n", i);
}
printf("반복 2 종료\\n");
}
void MultiThread()
{
function<void(int)> func = bind(MultiThread1, placeholders::_1); //placeholders : 파라미터 있을때 순서대로 들어온 파라미터를 쓰는 것이다.
//thread t(bind(MultiThread)); //C# 쓰레드와 다르게 바로 쓰레드를 실행할 수 있다.
thread t(func, 1);
thread t2(func, 2);
t2.join();
printf("t2.join\\n");
t.join();
printf("t.join\\n");
}
void MultiThread1(int number)
{
for (int i = 0; i < 100; i++) {
printf("%d : %d\\n", number, i);
}
printf("반복 %d 종료\\n", number);
}
공유자원 이면 생기는 문제(스레드 문제)
- 레이스 컨디션 ⇒ 스레드 사용하면 반드시라고 해도 좋을정도로 나온다.
Static 초기화
- C에서는 Static을 쓸때 반드시 전역으로 초기화를 해줘야 한다.
- a는 '데이터 영역'에 생기고 초기화할때 초기값이 결정된다.
class Test
{
public:
static int a;
int b = 0; //멤버 변수
};
int Test::a = 0; //C에서는 Static을 쓸때 반드시 전역으로 초기화를 해줘야 한다. / a는 '데이터 영역'에 생기고 초기화할때 초기값이 결정된다.
가상메모리
- 동적 할당을 힙이 아니라 ‘가상 메모리’에 하는것을 기억해라
- 메모리 관리 기법의 하나로, 컴퓨터 시스템에 실제로 이용 가능한 기억 자원을 이상적으로 추상화하여 사용자들에게 매우 큰 (주) 메모리로 보이게 만드는 것을 말한다.
- 각 프로그램에 실제 메모리 주소가 아닌 가상의 메모리 주소를 주는 방식이다.
- 가상적으로 주어진 주소를 가상 주소(virtual address) 또는 논리 주소(logical address) 라고 하며, 실제 메모리 상에서 유효한 주소를 물리 주소(physical address) 또는 실주소(real address)라고 한다.
- 가상 주소의 범위를 가상 주소 공간, 물리 주소의 범위를 물리 주소 공간이라고 한다.
- 가상 메모리는 크게 나누어 세그먼트(segment) 방식과 페이징 방식의 2종류가 있다.
virtualAlloc
- 미리 메모리 예약을 한다
- 예약 후 ~~
- 호출 프로세스의 가상 주소 공간에서 페이지 영역의 상태를 예약, 커밋 또는 변경한다.
- 이 함수에 의해 할당된 메모리는 자동으로 0으로 초기화됩니다.
- 다른 프로세스의 주소 공간에 메모리를 할당하려면 VirtualAllocEx 함수를 사용한다.
void* p = VirtualAlloc(nullptr, 128 * sizeof(Matrix), MEM_RESERVE, PAGE_READWRITE);
//가상 메모리에 메트리스 2차 배열 저장
for (int i = 0; i < 128; i++)
{
//가상 메모리는 애니메이션 저장 , 지형 관련해서 자주 사용한다.
void* temp = (BYTE*)p + sizeof(Matrix) * i; //(BYTE*)p : 3교시 녹음 듣자, 시작주소다. / 지삭주소 배열의 처음부터 점차 증가시키며 사용하겠다는 뜻이다.
VirtualAlloc(temp, sizeof(Matrix), MEM_COMMIT, PAGE_READWRITE); //MEM_COMMIT : 실제로 사용하겠다는 의미다. / PAGE_READWRITE : 읽을 수 있고 쓸 수 있는 방식으로
memcpy((BYTE*)temp, &matrix[i], sizeof(Matrix)); //(BYTE*)temp : 실제 시작주소 -> (BYTE*) 쓰는 이유는 위에서 void* 때문이다. / &matrix[i] : 위에서 만든 매트릭스의 i 번째 주소 / sizeof(Matrix) : 사이즈만큼 복사해라 / memcpy : 메모리카피
}
//가상 메모리 사용
Matrix* data = (Matrix*)p + 1; //첫번째 매트릭스 -> 01234 / 가상 메모리에 있는것을 거내서 사용하고 있다.
for (int row = 0; row < 4; row++)
{
for (int col = 0; col < 4; col++)
{
printf("%.0f\\t", data->m[row][col]); //%.0f : 소수점 몇번쨰 자리까지 출력한다는 뜻(이건 소수점 출력 한한다는 의미다.)
}
printf("\\n");
}
- nullptr : 할당할 지역의 시작 주소
- NULL인 경우 시스템은 지역을 할당할 위치를 결정한다.
- 128 * sizeof(Matrix) : 지역 크기(바이트)
- MEM_RESERVE : 메모리 할당 유형
- MEM_COMMIT : 지정된 예약된 메모리 페이지에 대한 메모리 요금(전체 메모리 크기 및 디스크의 페이징 파일)을 할당한다.
- 함수는 호출자가 나중에 처음에 메모리에 액세스할 때 콘텐츠가 0이 되도록 보장한다.
- 실제 실제 페이지는 가상 주소에 실제로 액세스하지 않는 한 할당되지 않는다.
- 한 단계에서 페이지를 예약하고 커밋하려면 를 사용하여 VirtualAlloc 을 MEM_COMMIT | MEM_RESERVE 호출한다.
- MEM_RESERVE : 메모리 또는 디스크의 페이징 파일에 실제 실제 스토리지를 할당하지 않고 프로세스의 가상 주소 공간 범위를 예약한다.
- VirtualAlloc 함수에 대한 후속 호출에서 예약된 페이지를 커밋할 수 있다.
- MEM_RESET : 시작 주소 및 지역 크기로 지정된 메모리 범위의 데이터가 더 이상 관심이 없음을 나타냅니다.
- 페이지를 페이징 파일에서 읽거나 쓸 수 없습니다.
- 그러나 메모리 블록은 나중에 다시 사용되므로 커밋 해제하면 안된다.
- 이 값은 다른 값과 함께 사용할 수 없습니다.
- MEM_RESET_UNDO : MEM_RESET 이전에 성공적으로 적용된 주소 범위에서만 호출해야한다.
메모리 계층
- Code 영역
- 프로세스가 실행할 ‘코드’와 매크로 상수가 기계어의 형태로 저장된 공간이다.
- 컴파일 타임에 경정되고, 코드를 바꿀 수 없게 Read-Only로 지정되어있다.
- Data 영역
- 코드에서 선언한 ‘전역변수’ 또는 ‘static 변수’ 등등이 저장된 공간이다.
- 전역변수 / static 값을 참조한 코드는 컴파일 하고 나면 Data 영역의 주소값을 가르키도록 바뀐다.
- Heap 영역
- 사용자의 ‘동적 할당’
- 할당과 해제는 프로그래머가 직접 해야한다.
- 공간이 비교적 크다(32비트 최대 4기가)
- 크기는 런타임에 정해진다.
- malloc, calloc으로 Heap 영역의 메모리를 사용할 수 있다.
- 데이터 배열의 크기가 확실하지 않고 변동이 있을 때 Heap 영역을 활용해서 메모리를 할당한다.
- 사용하고 난 다음 해제를 해야한다.
- Stack 영역
- 매개변수, 지역변수 - 함수
- 함수호출 할당, 함수호출 끝 해제
- 공간이 작다(보통 1메가)
- 크기가 컴파일 타임에 정해진다.
- 함수 안에서 선언된 지역변수, 매개변수, 리턴값, 돌아올 주소 등등이 저장되고 함수 호출시 기록하고 종료되면 삭제된다.
- 재귀함수가 너무 깊게 호출되거나, 함수가 지역변수를 너무 많이 가지고 있어 stack 영역을 초과하면 stack overflow 에러가 발생한다.
union - 공용체
- 내부에 여러가지 타입의 멤버 변수를 선언하지만 실제 사용할 때에는 하나의 멤버 변수만 사용할 수 있다.
- 구조체(struct)와 거의 동일하지만 ’모든 멤버 변수가 하나의 메모리 공간을 공유’한다는 점이 다르다.
union
{
struct
{
float _11, _12, _13, _14;
float _21, _22, _23, _24;
float _31, _32, _33, _34;
float _41, _42, _43, _44;
};
float m[4][4];
};
struct Vector3
{
union
{
struct
{
float x, y, z;
};
float v[3];
};
};
- Vector3의 배열을 x, y, z로 부를 수 있고 v[]로 부를 수 있다.
virtualAlloc
- RESERVE
- COMMIT
- VirtualFree
define
#define PI 3.14
float a = PI * 2.0f; //PI에 자동으로 3.14가 들어간다.
#define TRUE rand()%2 //TRUE가 0 ~ 2에서 랜덤한 수로 나와서 싸움이 날 수 있다(물리적으로)
if(a == TURE) {}
rand