동적할당 / 자료구조

메모리

메모리는 프로그램이 실행될 때 데이터를 잠시 보관하는 저장 장소입니다. 아주 쉽게 말하면 “컴퓨터의 책장”이라고 생각하세요.

간단한 비유 (책장):

각 칸(서랍)은 1바이트(또는 여러 바이트)의 공간을 가지고 있고, 칸마다 번호(주소)가 붙어 있습니다.

예시 ASCII 그림:

책장(메모리)
[0x100] [0x101] [0x102] [0x103] [0x104] [0x105] ...  <- 각각의 칸이 주소를 가짐
	0      0      42     0      ?      ?
  • 주소(address): 각 칸의 번호입니다. 주소를 알고 있으면 그 칸(메모리)에 들어있는 값을 읽거나 쓸 수 있습니다.
  • 포인터(pointer): 주소를 저장하는 변수입니다. 즉, 어떤 칸을 가리키는 종이(주소)를 들고 있다고 생각하면 됩니다.

아주 짧은 C 예제(개념 확인용):

int a = 10;        // a는 메모리의 어떤 칸에 10을 저장
int *p = &a;       // p는 a가 있는 칸의 주소를 저장
// &a는 a의 주소, *p는 p가 가리키는 칸의 값
printf("주소: %p, 값: %d\n", (void*)p, *p);

위 코드를 실행하면 p(주소)와 그 주소에 들어있는 값(10)을 볼 수 있습니다. 이 정도 개념만 알면 포인터와 메모리의 기본을 이해하는 데 충분합니다.

포인터

포인터는 메모리의 주소를 저장하는 변수입니다. 동적할당과 메모리 관리에서 매우 중요한 역할을 합니다.

포인터 타입은 type관련없이 8byte 자료형입니다.

int a = 10;
int *p = &a; // p는 a의 주소를 저장
printf("%d", *p); // p가 가리키는 곳의 값(10) 출력

동적할당된 메모리는 포인터로만 접근할 수 있습니다.

지역변수와 동적할당

지역변수는 함수가 끝나면 자동으로 소멸되지만, 동적할당된 메모리는 직접 해제하기 전까지 남아있습니다.

void foo() {
	int x = 10; // 지역변수, 함수 끝나면 사라짐
	int *p = malloc(sizeof(int)); // 동적할당, 함수 끝나도 남아있음
	*p = 20;
	// ...
	free(p); // 직접 해제 필요
}

할당 해제

동적할당한 메모리는 반드시 free로 해제해야 합니다. 해제하지 않으면 메모리 누수가 발생합니다.

int *p = malloc(sizeof(int) * 10);
// ... 사용
free(p); // 메모리 반환

메모리 누수

메모리 누수란, 할당한 메모리를 해제하지 않아 프로그램이 점점 더 많은 메모리를 차지하게 되는 현상입니다. 반복적으로 동적할당만 하고 해제하지 않으면 프로그램이 느려지거나 비정상 종료될 수 있습니다.

for(int i=0; i<1000; i++) {
	int *p = malloc(sizeof(int) * 100);
	// ... 사용
	// free(p); // 해제하지 않으면 누수 발생
}

실제 프로그램에서는 동적할당 후 반드시 free로 해제하는 습관이 중요합니다.

results matching ""

    No results matching ""