• 검색 결과가 없습니다.

12차시 – 동적 할당(3)

N/A
N/A
Protected

Academic year: 2022

Share "12차시 – 동적 할당(3)"

Copied!
25
0
0

로드 중.... (전체 텍스트 보기)

전체 글

(1)

12차시 – 동적 할당(3)

(2)

운영체제의 메모리 관리

운영체제의 메모리 할당/해제

– 프로그램 실행 시 메모리 제공

– 프로그램 실행 도중 메모리 제공/해제 – 프로그램 종료 시 모든 메모리 해제

운영체제의 메모리 관리

– 메모리 관리 테이블 운영

– 프로세스, 메모리 크기, 시작위치 관리 – 최적의 방법에 의해 메모리를 할당

(3)

메모리 확보/반납

잦은 메모리 확보/반납은 성능을 저하시킨다.

– 운영체제의 메모리 관리 테이블을 소진한다.

– 메모리 관리를 위해 해야 하는 많은 일이 있다.

좋은 메모리 사용

직접 메모리 관리를 해야 할 수도 있다.

– 고급 프로그래밍

– 실시간 성능이 중요시되는 게임

(4)

메모리 관련 오류들

확보되지 않은 공간에 접근

반납한 메모리 접근

확보에 실패한 것을 모르는 경우

그 외

(5)

메모리 누수

메모리가 새는 경우

– 사용 가능한 메모리가 줄어든다.

– 사용중인 메모리가 계속 늘어난다.

문제가 되는 경우

– 대형 시스템

– 장기간 동작하는 서버

(6)

메모리 누수

char *block;

block = malloc(10);

strcpy(block, “Hello”);

block = malloc(100);

strcpy(block, “World”);

free(block);

Hello block

(1)

(2)

Hello block

World

(3)

Hello block

World

(free) (malloc)

(malloc)

?

(7)

가비지 컬렉션

필요성

– 공간은 있으나 할당할 수 없는 상황 – 메모리 관리자(운영체제)의 역할이다.

– C에서는 없다(Java는 있다).

10 바이트 10 바이트 10 바이트 10 바이트 10 바이트

10 바이트 10 바이트 10 바이트

(1)

(2)

(3)

10 바이트 10 바이트 10 바이트

20 바이트

?

(8)

배열과 결합된 형태

int *piarr[5];

int i;

for( i = 0 ; i < 5 ; i++)

piarr[i] = malloc (sizeof(int) * 5 );

int * int *

int *

. . .

int int int int int int int

int int int int int

문제점은? 뒤에서 해결.

(9)

문자열의 정렬

저장된 문자열을 알파벳 순으로 정렬하라.

h e l l o \0

n i c e \0

t o \0

m e e t \0

y o u \0

*strptr[5]

(10)

문자열의 정렬

char *strptr[5];

char input[100], temp[100];

int i, j;

for (i = 0; i < 5; i++) {

gets(input); // 문자열을 입력 받은 후,

strptr[i] = malloc(strlen(input)+1); // 문자열 크기에 맞는 메모리 할당 strcpy(strptr[i], input); // 문자열 복사

}

// 버블 소트 시작

for (i = 0; i < 4; i++)

for (j = i; j < 5; j++)

if (strcmp(strptr[i], strptr[j]) > 0) { // 앞쪽 문자열이 더 크면 strcpy(temp, strptr[i]); // 앞 뒤 문자열 교환 strcpy(strptr[i], strptr[j]);

strcpy(strptr[j], temp);

}

메모리 문제가 있다.

(11)

문자열의 정렬

if (strcmp(strptr[i], strptr[j]) > 0) { strcpy(temp, strptr[i]);

strptr[i] = realloc(strptr[i], strlen(strptr[j])+1); // 메모리 조정 strcpy(strptr[i], strptr[j]);

strptr[j] = realloc(strptr[j], strlen(temp)+1); // 메모리 크기 조정 strcpy(strptr[j], temp);

}

h e l l o \0

n i c e \0

t o \0

m e e t \0

y o u \0

*strptr[5]

(6바이트 할당)

(5바이트 할당)

(내용을 바꾸려 하면 strptr[1]에서 메모리 부족으로 에러를 낸다.

(12)

문자열의 정렬

if (strcmp(strptr[i], strptr[j]) > 0) {

char *tempptr;

tempptr = strptr[i];

strptr[i] = strptr[j];

strptr[j] = tempptr;

} 0 1 2 3 4

h e l l o \0

n i c e \0

t o \0

m e e t \0

y o u \0

0 1 2 3 4

h e l l o \0

n i c e \0

t o \0

m e e t \0

y o u \0

화살표의 방향만 바꾸어주면 된다. 보기 쉽게 재정렬한 형태.

(13)

댕글링 포인터의 처리

0 1 2 3 4

h e l l o \0

n i c e \0

t o \0

m e e t \0

y o u \0

두 개의 공간은 더 이상 필요 없어 해제했다.

0 1 2 3 4

h e l l o \0

n i c e \0

y o u \0

두 개의 포인터는

댕글링 포인터가 되었지만, 이를 알 수 있는 방법은 없다.

0 1 2 3 4

h e l l o \0

n i c e \0

y o u \0

NULL NULL

댕글링 포인터로 두지 않고

NULL로 설정한다. 이것은 할당되지 않음을 의미하는 약속이다.

(14)

구조체와 결합된 자료형

struct { // 구조체의 배열로 선언한다.

int allocsize; // 할당한 공간의 크기를 넣는다. 처음에는 0을 넣는다.

char *ptr; // 할당할 메모리를 가리킨다.(전과 동일) } strptr[5];

// 메모리를 할당할 때

strptr[2].ptr = malloc(3);

strptr[2].allocsize = 3;

strcpy(strptr[2].ptr, “to”);

// 해당 메모리에 다른 문자열(tempstr)을 넣을 때는?

5 6 3 5 4

h e l l o \0

n i c e \0

t o \0

m e e t \0

y o u \0

allocsize ptr

(15)

이중 포인터와 동적 할당

int **numptr[5]; // ①

numptr[0] = malloc(sizeof(int *) * 10); // ②

*numptr[0] = malloc(sizeof(int) * 5); // ③

**numptr[0] = 1; // ④

*(*numptr[0] +1) = 6;

printf("%d\n", **numptr[0]);

0-99 100-199 200-299 300-399 400-499

0-9 10-19 20-29 30-39

1 6 3 9 4

14 18 12 10 19

24 22 29 26 21

37 39 36 32 34

① numptr

. . .

(16)

링크드리스트

배열의 단점

– 삽입, 삭제가 어렵다.

a b d e f Z

0 1 2 3 4 100

c

a b d e Y

0 1 2 3 4 100 101

Z

뒤로 한 칸씩 옮긴다.

a b c d e Y

0 1 2 3 4 100 101

Z

공백이 생겼으므로 c를 넣는다.

뒤로 밀 때 주의해야 한다.

(17)

링크드리스트

데이터가 어디에 있든 위치만 연결하면 된다.

a b d

e

z

(18)

링크드리스트

삽입

a

b

d e

z

c

a

b

d e

z

c

(19)

링크드리스트

struct node { int data;

struct node *next;

};

struct node *firstptr, *secondptr, *start;

firstptr = malloc ( sizeof(struct node) ); // ① 첫 번째 데이터 firstptr->data = 10;

start = firstptr; // 링크드리스트의 시작을 기억함

secondptr = malloc ( sizeof(struct node) ); // ② 두 번째 데이터 secondptr->data = 20;

firstptr->next = secondptr; // ③ secondptr->next = NULL; // ④

(20)

링크드리스트

20 1100

10

NULL

1100

1200 start

20 firstptr

10

NULL secondptr

1100

1200

start

struct node

struct node

(21)

링크드리스트

struct node *ptr, *start;

// 이미 노드가 생성되고 데이터가 들어있어야 한다.

ptr = start; // 링크드리스트의 시작점부터 for( i = 0 ; i < 5 ; i++)

ptr = ptr -> next; // 다섯번 건너뜀

printf(“여섯번째 노드의 데이터는 %d\n”, ptr->data );

10 20 start

30 40 50

ptr

60 ptr = start

i=0 i=1 i=2 i=3 i=4

next next next next next

ptr->data = 60

(22)

링크드리스트

10 20 start

30 40 50 60

25

10 20 start

30 40 50 60

25 ptr

newnode

(23)

링크드리스트

struct node *ptr, *newnode;

ptr = start; // 링크드리스트의 시작점부터 insertvalue = 25; // 추가할 데이터

while (ptr) {

if (ptr->next->data > insertvalue) { // 삽입할 위치를 찾았다면 newnode = malloc( sizeof(struct node) );// 새 노드를 만들고 newnode -> data = insertvalue; // 값을 채우고

newnode -> next = ptr->next;// 추가된 노드의 다음 데이터 화살표 설정 ptr->next = newnode; // 앞 노드의 다음 데이터 화살표는 새 노드 break; // 노드 추가 완료

}

ptr = ptr -> next; // 다음 노드로 이동 }

(24)

링크드리스트

특징

– N번째 데이터에 도달하려면 앞에서부터 찾아야 한다.

– 링크가 끊어지면 데이터가 유실된다.

– 가장 마지막 노드의 next는 NULL이다. 데이터의 끝을 의미한다.

(25)

링크드리스트

단점과 그 해결

– N번째 데이터를 찾기 위해 오래 걸린다.

• 해결 : 배열의 포인터로 색인을 만든다.

– 운영에 데이터보다 링크가 더 많다.

• 해결 : 데이터 부분을 더 크게 한다.

1번 데이터 11번 데이터 21번 데이터 31번 데이터

포인터의 배열

a

b

c

d

e

f

a b c d e

f g h i j

k l m

n o

해결책을 찾는 것은 여러분의 몫

참조

관련 문서

현재 기독교 신학계를 지배하고 있는 신학 의 역사적 배경 및 그 사상적, 철학적 계보 및 배경, 신학적 의미를 연구 분석 비평을 통하여 정확한

동적 수축 (Dynmic Contraction) 근수축 형태. 등속성 수축 (Isokinetic

프로세스들은 시간 할당량 동안 CPU를 할당 받아 실행되는데, 이 시 간 동안 실행을 종료하지 못하면 운영체제에 의해 준비 상태로 쫓겨 나고, 준비 큐의 다음 프로세스가

 CPU 내에 데이터가 담겨 있는 메모리 주소를 임시 저장하는 장소.  CPU 내에 데이터가 담겨 있는 메모리 주소를

링크드리스트( Linked List ) 라고 한다. 매우 중요하지만,

- 함수의 인자로 배열이 전달되면 배열의 기본 주소가 (배열의 내용이 아님) call-by-value로 전달됨...

– Woking set 크기 만큼의 프레임 할당. ●

step(A,B,C,D,ui,t) % 상태공간으로 정의된 시스템에 input ui에 대한 step response를 시간 t에 대해 그린다.... ■