본문 바로가기

Programming/C

[C언어] 25장-2. 메모리의 동적 할당

반응형

전역변수와 지역변수로 해결이 되지 않는 상황

malloc은 메모리공간을 할당할 때 사용하는 함수 [잠시 변수 할당]

 

1. 지역변수일 경우

ReadUserName : 이름을 입력받고 입력받은 이름을 반환하는 함수

 

main : ReadUserName의 주소값을 반환해 출력

-> 문자열을 입력받기 위한 메모리 공간이 필요하다.

 

작동 순서

1. 메모리 공간 할당

2. 입력

3. 반환

 

-> name2의 출력이 끝났을 때

name1이 가리키는 것 : 첫번째로 입력한 문자열

name2가 가리키는 것 : 두번째로 입력한 문자열

 

-> ReadUserName()을 name1에 반환

-> name은 지역변수이므로 return과 동시에 소멸한다.

-> name1에는 소멸된 변수를 가리킨다. [에러 : 출력은 될수도 있지만 잘못된 코드]

 

2. 전역변수일 경우

ReadUserName 함수

1. 전역변수 name

2. gets

3. return

 

-> 전역변수는 고정 [삭제, 추가 불가]

 

 -> name1과 name2을 입력받으면 두 개의 메모리공간 할당해야하지만

하나의 메모리 공간을 공유한다.

 

-> 출력을 하면 name1을 덮어써서 name1과 name2과 같아진다.

 

 

 

 

해결 방법

=>어떤 형태의 메모리 할당이 필요할까?

 


ReadUserName이 여러번 호출될때 각각 메모리가 할당되는 방법

 

함수가 호출되었을 때 메모리공간이 할당이 되어서 원하는 시간에 지울 수 있는 방법

: malloc()

-> 프로그래머가 지우지 않는 이상 계속해서 메모리에 남아있다.

 

데이터 영역 : 전역 변수

힙 영역 : 프로그래머가 원하는 시점에 할당과 해제하는 변수

스택 영역 : 지역 변수

#include <stdlib.h>
void* malloc(size_t size); //힙 영역으로의 메모리 공간 할당
void free(void * ptr); //힙 영역에 할당된 메모리 공간 해제
int main(void)
{
 void* ptr1= malloc(4);
 void* ptr2= malloc(12);
 
 ...
 free(ptr1);
 free(ptr2);
 ...
 }

-> 포인터연산을 하기 위해서는 데이터형변환이 필요하다

 

*ptr1= 20을 하기위해서는

int* ptr=(int *) ptr1;

*ptr1 = 20;

malloc 함수의 반환형이 void형 포인터인 이유

void* ptr1=malloc(sizeof(int)); //4
void* ptr2=malloc(sizeof(double)); //8
void* ptr3=malloc(sizeof(int)*7); //28 //7개 변수의 배열
void* ptr4=malloc(sizeof(double)); //72 //9개 변수의 배열
int* ptr1=(int*)malloc(sizeof(int));
double* ptr2=(double *)malloc(sizeof(double));
int* ptr3=(int*)malloc(sizeof(int)*7);
double* ptr4=(double *)sizeof(double)*9);

-> malloc함수는 메모리의 용도를 모르기 때문에 포인터형의 결정을 못한다.

-> 형변환 과정을 통해 할당된 메모리의 주소값을 저장


힙 영역으로의 접근

int main(void)
{
 int* ptr1=(int *)malloc(sizeof(int));
 int* ptr2=(int *)malloc(sizeof(int)*7);
 int i;
 
 *ptr1=20;
 for(i=0; i<7; i++)
 	ptr2[i]=i+1;
printf("%d \n", *ptr1);
for(i=0; i<7; i++)
	printf("%d ", ptr2[i]);
free(ptr1);
free(ptr2);
return 0;
}

-> 힙 영역으로의 접근은 포인터를 통해서만 이루어진다.

 

int* ptr=(int*) malloc(sizeof(int));
if(ptr==NULL)
{
 //메모리 할당 실패에 따른 오류의 처리
}

-> malloc 호출 후 반환된 주소값이 NULL이 아닌지 확인 후 메모리 공간을 사용해야 한다.


동적 할당인 이유

: 컴파일 시 할당에 필요한 메모리 공간이 계산되지 않고, 실행 시 할당에 필요한 메모리 공간이 계산되므로 동적할당

 

free 함수를 호출하지 않으면

: 할당된 메모리 공간은 메모리라는 중요한 리소스를 계속 차지하게 된다.

-> 프로그램이 종료되면 할당된 메모리가 소멸된다. [종료시 모든 리소스는 소멸된다.]

 

꼭 free함수를 호출해야 하는 이유는 무엇인가?

: fopen 함수와 쌍을 이루어 fclose 함수를 호출하는 것과 유사하다.

 

malloc을 호출하면 반드시 free 호출을 해야한다.


문자열 반환 함수 해결

char* ReadUserName(void)
{
 char* name=(char *)malloc(sizeof(char)*30);
 printf("What's your name? ");
 gets(name);
 return name;
 }
int main(void)
{
 char* name1;
 char* name2;
 name1=ReadUserName();
 printf("name1: %s \n", name1);
 name2=ReadUserName();
 printf("name1: %s \n", name2);
 
 printf("again name1: %s \n", name1);
 printf("again name2: %s \n", name2);
 free(name1);
 free(name2);
 return 0;
}

1. 메모리 할당 -> 함수를 빠져나가도 소멸되지 않는다.

2. 입력

3. 반환

 


calloc & realloc

 

-> malloc, calloc, realloc 함수 호출을 통해서 할당된 메모리 공간은 모두 free 함수호출을 통해서 해제한다.

반응형