공부/Unity

24.04.23

월러비 2024. 4. 24. 09:12

새로 생성한 스크립트

  • 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()을 해야 쓰레드가 작동한다.
    • 1의 반복과 2의 반복이 섞이면서 실행된다.
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 영역
    1. 사용자의 ‘동적 할당’
    2. 할당과 해제는 프로그래머가 직접 해야한다.
    3. 공간이 비교적 크다(32비트 최대 4기가)
    4. 크기는 런타임에 정해진다.
    • malloc, calloc으로 Heap 영역의 메모리를 사용할 수 있다.
    • 데이터 배열의 크기가 확실하지 않고 변동이 있을 때 Heap 영역을 활용해서 메모리를 할당한다.
    • 사용하고 난 다음 해제를 해야한다.
  • Stack 영역
    1. 매개변수, 지역변수 - 함수
    2. 함수호출 할당, 함수호출 끝 해제
    3. 공간이 작다(보통 1메가)
    4. 크기가 컴파일 타임에 정해진다.
    • 함수 안에서 선언된 지역변수, 매개변수, 리턴값, 돌아올 주소 등등이 저장되고 함수 호출시 기록하고 종료되면 삭제된다.
    • 재귀함수가 너무 깊게 호출되거나, 함수가 지역변수를 너무 많이 가지고 있어 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

  • 랜덤을 만들어 주는 함수

'공부 > Unity' 카테고리의 다른 글

24.04.25  (1) 2024.04.25
24.04.24  (8) 2024.04.25
24.04.22  (0) 2024.04.22
24.04.19  (0) 2024.04.22
24.04.18  (1) 2024.04.18