본문으로 바로가기

[C] 동적할당 보고서

category Layer 7/assignment 2019. 4. 12. 21:20

[1] 동적할당 vs 정적할당 

정적할당이란 프로그램이 시작되기전에 결정되는 메모리를 말한다.

프로그램이 실행되는 도중에 크기가 변경될 수 없으며, 처음 결정된 크기보다 더 큰 입력이 들어오면 오버플로우가 일어나 다른 메모리의 주소가 변조될수있다. 처음 결정된 크기보다 더 작은 입력이 들어온다면, 남은 메모리는 낭비된다.

프로그램이 종료되어야 메모리가 해제된다.

이렇게 정적할당으로 결정된 메모리는 스택에 저장된다.

https://sunrinjuntae.tistory.com/25

스택과 힙이 무엇인지는 여기서!!


동적할당은 사용자가 프로그램의 실행도중에 메모리를 할당 받는것이다.

필요한 만큼만 할당을 받고, 또 원할때 사용하고 반납할수있다. 메모리를 절대로 낭비하지 않을수있으며, 메모리를 매우 효율적으로 사용할수있다.

동적할당으로 결정된 메모리는 Heap이라는 자료구조에 들어간다. 

동적할당은 Stack에 할당된 메모리와는 다르게 프로그램이 종료된다고 해서 자동으로 메모리가 비워지지않는다.

그래서 우리가 직접 메모리를 해제해주어야 하는데, 왜 이래야하는지는 이따가 알아보도록하자.





[2] 동적 메모리 할당법

일단 malloc, calloc, realloc으로 메모리를 할당한다.

그리고 할당된 메모리를 사용하고, free함수를 이용하여 선언한 메모리를 해제해준다.

위의 그림이 동적할당 사용의 과정이다.

이제 동적할당 함수 ( malloc, free ) 등에 어떠한 인자를 전달해야하는지 알아보자.


<malloc의 원형>

*malloc유형의 함수들의 헤더파일은 stdlib.h 이다!

void *malloc(size_t_Size);

포인터 = (포인터의 자료형으로 형변환)malloc(크기);

메모리 할당에 성공하면 그 메모리의 시작 주소를, 실패하면 null을 반환한다.


calloc은 메모리를 할당한후 메모리를 전부 0으로 할당한다.

이는 배열을 선언하고나서 배열값을 모두 0으로 바꿔야할때 몹시 유용하다!

realloc은 선언되어있는 메모리의 크기를 변경할때 사용한다.


malloc의 원형에서 볼수있듯이 말록은 포인터변수를 대상으로 사용하고, 포인터의 자료형으로 형변환을 해줘야한다.

예를들어서 ..

1
2
3
int *pt; //포인터변수 pt선언
pt = (int*)malloc(sizeof(int)); //int형으로 형변환!
                                //포인터변수 pt는 4byte만큼 메모리를 할당받았다.
cs


이런식이다!

int형으로 포인터를 선언해주었으므로 자료형을 맞춰주는것이 보기도편하고 쓰기도 좋다.

malloc 외에도 기존 할당된 메모리의 크기를 변경해주는 realloc과...

메모리를 할당하고 자동으로 0으로 초기화해주는 calloc이 있다는것을 알아두자.

그다음에는 free함수의 원형을 보자.



<free의 원형>

void free(void *_Block);

free(메모리를 할당한 변수 명)

위의 그림은 동적할당관련 함수들을 정리해놓은것이니 참고하면 좋을듯하다.


원형을 보면 알겠지만, free함수는 매우매우 간단하다. 예시를 보자.

1
2
3
int *pt; //포인터변수 pt선언
pt = (int*)malloc(sizeof(int)); 
free(pt) // 메모리 해제
cs

위의 예시처럼 단순히 free의 인자에 포인터변수를 전달해주면된다.

free는 malloc류 함수를 사용했다면, 선택이 아니라 " 필수 " 이다.

그 이유는 무엇일까?





[3] free함수의 중요성

일단 free함수의 중요성을 생각하기전에 메모리 누수에 대하여 알아보고가자.

메모리누수는 할당된 메모리가 더이상 사용되지 않지만, free로 해제되지 않았을때 발생한다.

그 경우는 크게 3가지로 나눌수있는데..


1. 메모리 주소를 찾을수 없는 경우

2. free 함수가 호출되어야하는데 호출되지 않은경우

3. 메모리 주소가 손실된 경우


이다.


예시를 들어보자. 

아래는 예시코드이다.

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
int main()
{
    int *pt= (int*)malloc(sizeof(int)); // 포인터변수 pt에 4바이트 메모리 할당
    
    *pi=10// 포인터변수 pt에 10대입
    
    pi = (int*)malloc(sizeof(int)); // 포인터변수 pt에 4바이트 메모리 다시 할당
    
    // 처음 동적할당한 메모리의 주소를 잃어버림 :(
}
cs

위 코드가 메모리 주소를 찾을수 없는 경우이다..

이미 동적할당을 해둔 메모리에다가 free도 사용하지않고 바로 동적할당을 해주었다.

이미 원래있던 메모리주소는 바이바이인 상황이다... 이렇게되면 보안 취약점이 발생할수도있다고 한다.

이런경우에는 free()를한다고 해도 메모리가 손실되고, free도 잘안되지 않으므로 꼭! 확인해보도록 하자.






[4] 댕글링 포인터

댕글링포인터란, 해제된 메모리영역 ( free ) 을 가리키고 있는 포인터이다.

댕글링포인터는..

- 메모리 접근시 예측 불가능한 동작 ( 해제된 메모리영역에 무엇이있을지 모름 )

- 메모리 접근 불가시 Sgmetation fault ( 허용되지않은 메모리공간에 침범할때 ) 발생

- 잠재적인 보안 위험

와같은 다양한 문제를 야기한다.


이런 댕글링포인터는, 메모리를 해제한 후, 해제된 메모리에 접근할때 주로 일어난다.





'Layer 7 > assignment' 카테고리의 다른 글

[GIT] git 보고서  (0) 2019.06.10
[Linux] 리눅스 보고서  (0) 2019.05.26
[C] 달팽이 배열  (0) 2019.04.09
[C] 포인터 보고서  (0) 2019.04.03
[C] 함수 보고서  (0) 2019.04.03