메모리 할당
메모리 할당
메모리를 언제 할당하느냐에 따라 정적 할당과 동적 할당으로 나뉜다
정적 할당
-
컴파일 단계에서 메모리를 미리 할당하는 방법
-
Stack 영역에 할당
-
메모리 공간이 얼마나 필요한 지 항상 알 수 없기에 효율적이지 못함
-
자칫하면 과도하게 메모리가 할당되어 남는 공간이 생길 수가 있음. 또한, 메모리가 필요해져도 추가로 할당 할 수 없음
-
함수가 끝날 시에 할당된 메모리가 자동으로 해제되므로 직접 메모리를 해제하지 않아도 됨
동적 할당
-
런타임에서 메모리를 필요할 때마다 할당하는 방법
-
Heap 영역에 할당
-
미리 할당해두는 것이 아니기 때문에 할당해둔 메모리 공간이 부족하거나 남는 현상이 발생하지 않음
-
메모리가 자동으로 해제되지 않기 때문에 메모리를 직접 해제해줘야 함
-
메모리를 해제해주지 않으면 메모리 누수 현상이 발생
-
게임 프로그래밍을 할 때 많이 사용됨
가상 메모리
메모리 공간보다 더 많은 주소 공간을 필요로 할 때 사용함
주소 사상 기법(주소 매핑 기법)이라는 기법을 사용함
ex )
빈 공간(0x000 ~ 0x100) - a.txt(0x100 ~ 0x200) - 빈 공간(0x200 ~ 0x300) - b.exe(0x300 ~ 0x400)
이렇게 할당 된 주소 공간이 있다고 가정했을 때,
가상 메모리의 주소 매핑은 주소를 연속적으로 사용할 수 있도록
0x000 ~ 0x100, 0x100 ~ 0x200 으로 매핑이 됨.
예시
#include <stdio.h>
#include <Windows.h>
void Allocate_Malloc()
{
void* p = malloc(20); //20 byte 할당
int* pi = (int*)p;
pi[0] = 1;
*(pi + 1) = 2;
for (int i = 0; i < 5; i++)
pi[i] = i + 1;
for (int i = 0; i < 5; i++)
printf("pi[%d] = %d\n", i, pi[i]);
free(p);
}
void Allocate_New()
{
int* a = new int(); //new는 예약어이자 명령어. 4byte 할당
*a = 10;
printf("*a = %d\n", *a);
delete a;
a = nullptr; //a에 쓰레기 값이 들어가는 걸 방지하기 위함
int* b = new int[5];
b[0] = 1;
*(b + 1) = 2;
//*b++; //연산자 우선순위가 ++이 높아서 다음 주소로 접근하겠다는 뜻이 됨
for (int i = 2; i < 5; i++)
*(b + i) = i + 1;
for (int i = 0; i < 5; i++)
printf("b[%d] = %d\n", i, b[i]);
delete[] b; //배열로 할당된 것은 배열 기호를 붙여줘야 함.
b = nullptr;
}
struct Matrix
{
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];
float m2[16];
};
};
void Union()
{
int count = 0;
Matrix matrix;
for (int y = 0; y < 4; y++)
{
for (int x = 0; x < 4; x++)
{
matrix.m[y][x] = ++count;
}
}
printf("matrix.m[1][2] = %f\n", matrix.m[1][2]);
printf("matrix.m[1][2] = %f\n", matrix._23);
printf("matrix.m2[6] = %f\n", matrix.m2[6]);
printf("%p %p %p\n", &matrix.m[1][2], &matrix._23, &matrix.m2[6]);
}
void Stack_Overflow()
{
//Matrix matrix[1024][1024];
//unsigned char a[1024*1009]; //스택 프레임의 크기 약 1MB, 1024 * 1010
Matrix* matrix = new Matrix[1024 * 1024]; //Heap 구역에 할당되기 때문에 허용 됨
delete[] matrix;
matrix = nullptr;
}
void Print_Matrix(Matrix* matrix)
{
for (int row = 0; row < 4; row++)
{
for (int col = 0; col < 4; col++)
{
printf("%.0f\t", matrix->m[row][col]); //.0f : 소수점 제거
}
printf("\n");
}
printf("Matrix Address : %p\n\n", matrix);
}
void Virtual_Alloc()
{
Matrix* matrix = new Matrix[128];
int count = 0;
for (int m = 0; m < 128; m++)
{
for (int row = 0; row < 4; row++)
{
for (int col = 0; col < 4; col++)
{
matrix[m].m[row][col] = count++;
}
}
}
void* p = VirtualAlloc(nullptr, sizeof(Matrix) * 128, MEM_RESERVE, PAGE_READWRITE);
//예약된 공간의 시작 주소를 p에 저장
for (int i = 0; i < 128; i++)
{
void* temp = (BYTE*)p + sizeof(Matrix) * i;
VirtualAlloc(temp, sizeof(Matrix), MEM_COMMIT, PAGE_READWRITE);
memcpy_s((BYTE*)temp, sizeof(Matrix), &matrix[i], sizeof(Matrix));
}
delete[] matrix;
matrix = nullptr;
Print_Matrix((Matrix*)p + 0);
Print_Matrix((Matrix*)p + 100);
VirtualFree(p, 0, MEM_RELEASE);
}
int main()
{
Allocate_Malloc();
Allocate_New();
Union();
Stack_Overflow();
printf("\n\n");
Virtual_Alloc();
return 0;
}