[C언어] 8. 메모리관리와 메모리 동적할당




제가 책(윤성우의 열혈 C 프로그래밍)을 보다가 까먹었던 부분만 포스팅 하는 것입니다!

순서가 뒤죽박죽이어도 이해해주세요~~!

C언어의 메모리 구조



프로그램 실행 시 운영체제에 의해서 마련되는 메모리 구조는 다음과 같습니다.

코드영역: 실행할 프로그램의 코드가 저장되는 메모리 공간


데이터영역: 전역변수와 static으로 선언되는 static 변수 할당

이 영역에 할당되는 변수들은 프로그램의 시작과 동시에 메모리 공간에 할당되고,
프로그램 종료 시 까지 남아있게 됩니다.


스택영역: 지역변수와 매개변수 할당

이 영역에 할당되는 변수들은 선언된 함수를 빠져나가면 소멸됩니다.


힙 영역: 데이터, 스택 영역에 할당되는 변수들은
 
생성과 소멸의 시점이 이미 결정되어 있습니다.

그래서 C언어에서는 프로그래머가 원하는 시점에 변수를 할당하고 소멸하도록 지원하는데,

이러한 유형의 변수들은 이 힙 영역에 할당됩니다.



메모리의 동적 할당



전역변수와 지역변수로 해결이 되지 않는 상황을 보겠습니다.

함수를 이용해서 사용자의 이름을 저장하고 싶은 것인데요~

첫번째는 지역변수를 사용한 경우입니다

#include <stdio.h>

//이름을 저장해서 반환하는 함수
char* your_name(void)
{
	char name[30]; //지역변수로 선언
	printf("이름을 입력하세요:");
	gets(name);
	return name;
}

int main(void)
{
	char * name1;
	
	name1=your_name();
	
	printf("%s",name);

	return 0;
}



위의 경우는 에러를 발생시키는데,

그 이유는 함수 your_name을 빠져나오면서 그 안의 선언된 지역변수들은

모두 소멸되어서 name1에는 쓰레기 값이 저장되기 때문입니다.

그렇다면 전역변수를 사용하면 문제가 해결될까요?


#include <stdio.h>
char name[30]; //전역변수로 선언

char* your_name(void)
{
	printf("이름을 입력하세요:");
	gets(name);
	return name;
}

int main(void)
{
	char* name1;
	char* name2;
	name1=your_name();
	name2=your_name();
	
	printf("%s",name1);
	return 0;
}



전역변수를 사용하면 위의 경우와 같이 여러명의 이름을 받을 때,

다른 이름을 덮어쓰는 문제가 발생합니다.

이를 해결해주는 것이 힙 영역에 할당되는 변수입니다.

힙 영역의 메모리 공간 할당과 해제는 malloc과 free함수로 할 수 있습니다.


#include <stdlib.h>

int *ptr=(int *)malloc(sizeof(int)*7); //동적할당

free(ptr); //동적해제



그리고 malloc함수를 선언했으면 꼭 free함수로 동적해제를 해주어야합니다~!

그럼 아까 문제를 malloc을 써서 해결해보겠습니다.


#include <stdio.h>

char* your_name(void)
{
	//동적할당
	char * name=(char *)malloc(sizeof(char)*30);
	printf("이름을 입력하세요:");
	gets(name);
	return name;
}

int main(void)
{
	char* name1;
	char* name2;
	name1=your_name();
	name2=your_name();
	
	printf("%s",name1);
	printf("%s",name2);
	
	free(name1); //동적해제
	free(name2);
	return 0;
}



문제가 깔끔히 해결되는 것을 보실 수 있습니다~!



calloc과 realloc 함수



힙 영역에 메모리 공간을 할당하는 함수로 calloc이 있습니다.

#include <stdlib.h>

int * ptr=(int *)calloc(7,sizeof(int));

//인자만 다를 뿐 malloc과 동일합니다.



그리고 힙에 할당된 메모리 공간 확장 시에는 realloc 함수를 이용합니다~


#include <stdlib.h>

int main(void)
{
	int *arr=(int *)malloc(sizeof(int)*3); //길이가 3인 int형 배열 할당
	
	arr=(int *)realloc(arr,sizeof(int)*5); //길이가 5인 int형 배열로 확장
}