소개

앞선 python의 closure 에 대한 글을 작성하다가 문뜩 이런 생각이 들게 되었습니다.

  • Closure에서 nonlocal 변수들은 메모리에서 어떻게 저장되고 처리가 되는거지?
  • scop(외부함수)에 묶여 있는 변수(nonlocal)들은 nested function을 return 하고 사라지는데 어떻게 남아있게 되는거지?

이런 질문이 들어 closure 의 메모리 처리 방법에 대해서 찾아보고, 관련 내용을 정리해보려 합니다.

먼저, C/Assembly 관점에서 프로세스가 실행될 때의 메모리 구조는 아래와 같습니다.

Machine Languge / C / Assembly 관점에서 메모리

영역역할
Code기계어가 쌓이는 영역이다.
쌓인 기계어를 CPU가 수행해 프로그램 작동된다.
Data전역변수, 정적변수, 상수가 저장된다.
내부적으로 변수와 상수(write 막기위해)는 분리해 저장한다.
Stack함수 호출시 사용한다.
함수의 매개변수, 지역변수, 반환 주소값 저장한다.
크기가 작다.
Heap동적 사용할 수 있다.
malloc() / free() 를 사용하여 할당 및 해제 가능하다.
주로 동적으로 메모리 잡고 포인터로 참조된다.

Closure 메모리 사용

closure는 함수로 구현이 되는 만큼, 함수가 call 되고 return 될시 사용되어지는 stack 의 컨셉을 이용합니다.

Stack frame 은 아래와 같은 특징을 가집니다.

  • 함수가 call 될 때 분리된 scop 으로 사용 됨.
  • LIFO(Last In First Out) 방식으로 마지막으로 들어간 데이터가 먼저 나오는 형식으로 데이터를 관리함.
  • 만약 함수가 return 되면  사용하였던 stack frame 은 pop 되어 다음 함수가 사용할 수 있게 비워줌.

그런데, C/Assembly 이외 대부분의 higher level 프로그래밍 언어 관점에서는 stack을 flat array 대신에 linked list 또는 hash table 로 구현이 되어 있습니다. 이러한 방법 때문에 stack을 runtime에 재정렬을 할 수 있게 하고, 물리적 메모리 레이아웃에 제한을 받지 않도록 해줍니다.  그리고 stack을 linked list 또는 hash table 로 구현을 했다는 것은 결국 c/assembly 관점에서의 heap을 이용하여 구현이 되었다고 볼 수 있습니다.

즉, higher level language 에서의 stack은 실제 C나 Assembly level 에서의 heap 을 이용하여 linked list 또는 hash table로 구현이 된다고 볼 수 있습니다.

python에서 아래와 같은 closure 사용한 코드의 메모리 구조를 본다면 아래와 같습니다.

def outer_func(x):
    num = 1
    def inner_func():
        nonlocal num
        num = num + x
        print(num)
    return inner_func

myfunc = outer_func(10)
myfunc()
closure memory

참고

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

Back To Top