Garbage collection: Difference between revisions
Jump to navigation
Jump to search
(→Basic) |
|||
Line 13: | Line 13: | ||
C/C++에서 흔히 겪는 메모리 문제를 정리하면: | C/C++에서 흔히 겪는 메모리 문제를 정리하면: | ||
메모리 오염(corruption) 문제: | 1. 메모리 오염(corruption) 문제: | ||
버퍼 오버플로우 | 1.1 버퍼 오버플로우 | ||
double free: free한 포인터를 또 free | 1.2 double free: free한 포인터를 또 free | ||
dangling pointers: 해제된 메모리를 다시 참조 | 1.3 dangling pointers: 해제된 메모리를 다시 참조 | ||
메모리 누수 | 2. 메모리 누수 | ||
이렇게 크게 나눌 수 있는데 1의 문제는 GC로 해결 가능하다. | 이렇게 크게 나눌 수 있는데 1의 문제는 GC로 해결 가능하다. | ||
Line 26: | Line 26: | ||
메모리 누수를 다시 두 개로 나눠 생각하면: | 메모리 누수를 다시 두 개로 나눠 생각하면: | ||
접근 불가능한 객체에 대한 누수(lost objects): 더 이상 해당 객체에 접근을 할 수 없지만 반환되지 않은 것들 | 2.1 접근 불가능한 객체에 대한 누수(lost objects): 더 이상 해당 객체에 접근을 할 수 없지만 반환되지 않은 것들 | ||
더 이상 사용하지 않는 객체에 대한 누수(useless objects): 도달은 가능한데 더 이상 사용하지 않는 것들 | 2.2 더 이상 사용하지 않는 객체에 대한 누수(useless objects): 도달은 가능한데 더 이상 사용하지 않는 것들 | ||
핵심은 두 번째 해당하는 녀석인데, 먼저 여기서 아주 간략히 GC의 작동 원리부터 이야기 하면, 사실 별 것 없다. | 핵심은 두 번째 해당하는 녀석인데, 먼저 여기서 아주 간략히 GC의 작동 원리부터 이야기 하면, 사실 별 것 없다. |
Latest revision as of 08:25, 1 April 2016
Overview
Garbage collection - Automatic Memory allocating and deallocating 내용 정리
Basic
C/C++ 을 주로 사용하는 사람들에게는 Java 나 C# 에서 제공하는 가비지 컬렉터가 마치 모든 것을 해결해 줄것만 같은 도구일 수도 있다. 하지만 결론적으로, 그런것은 없다. 간단하게, 가비지 컬렉터는 "완벽하게" 동작하지는 않는다.
아래는 이와 같은 생각을 정리한 글이다<ref>http://minjang.egloos.com/2372567</ref>.
자바나 C# 같은 언어들은 가비지 컬렉터(garbage collector, GC)가 있어 C/C++에서 골치 아픈 메모리 누수 문제를 해결해준다는 인식이 초보자 혹은 나 같이 GC를 많이 써보지 않은 사람에게 널리 퍼져있다. 이건 정말 위험한 생각이다. GC는 일부 메모리 문제를 해결하지 모든 메모리 누수 문제를 해결해 줄 수 없다. C/C++에서 흔히 겪는 메모리 문제를 정리하면: 1. 메모리 오염(corruption) 문제: 1.1 버퍼 오버플로우 1.2 double free: free한 포인터를 또 free 1.3 dangling pointers: 해제된 메모리를 다시 참조 2. 메모리 누수 이렇게 크게 나눌 수 있는데 1의 문제는 GC로 해결 가능하다. 단순 배열에 대한 버퍼 오버플로우는 mananged 환경의 언어들의 배열 범위 검사로 해결된다. 명시적으로 free/delete를 할 필요 없으니 double free 같은 문제도 없다. 그런데 메모리 누수는 GC라 해도 완벽히 잡아낼 수 없다. 메모리 누수를 다시 두 개로 나눠 생각하면: 2.1 접근 불가능한 객체에 대한 누수(lost objects): 더 이상 해당 객체에 접근을 할 수 없지만 반환되지 않은 것들 2.2 더 이상 사용하지 않는 객체에 대한 누수(useless objects): 도달은 가능한데 더 이상 사용하지 않는 것들 핵심은 두 번째 해당하는 녀석인데, 먼저 여기서 아주 간략히 GC의 작동 원리부터 이야기 하면, 사실 별 것 없다. 근본 원리는 할당 받은 메모리에 접근할 수 있는 경로가 더 이상 존재하지 않는다면 이 메모리는 사용되지 않는 것으로 간주하고 GC가 자동적으로 반환하는 것이다. 코드까지 쓰기는 귀찮고(…) 대표적인 예로 메모리를 할당 받은 변수가 지역 변수라서 해당 스코프를 벗어나면 더 이상 접근 불가능한 경우가 있다. 그러나 문제는 두 번째에 해당하는 문제, 즉 도달은 가능한데 더 이상 사용하지 않는 객체에 대한 메모리 누수이다. 조금 극단적인 경우지만 이런 서버 프로그램의 예를 생각해보자. 클라이언트가 접속할 때 마다 Client라는 자료 구조를 하나 할당하고 전역 리스트에 이 Client 객체를 넣는다. 클라이언트가 접속을 끊으면 해당 Client 자료 구조를 리스트에서 삭제한다. 만약 이렇게만 작동한다면 GC는 똑똑히 작동한다. 2번 과정에서 더 이상 해당 Client 자료 구조에 대한 접근이 사라지므로 GC는 이 객체를 해제할 수 있다. C/C++ 처럼 명시적으로 Client 객체를 free/delete 할 필요는 없다. 그러나 문제는 프로그램이 복잡해지면 2번 과정에 실수가 있을 수 있다. 분명 더 이상 객체가 사용되지 않는데 프로그램 어딘가에 이 객체로 접근할 수 있는 길이 남아 있는 것이다. 극단적으로 이야기 하면 프로그래머가 2번 과정을 실수로 빼먹는 경우다. 아무리 이 Client 객체가 사용되지 않지만 전역 리스트에 자리를 차지하고 있으니 GC는 이것이 언젠가는 사용될 것이라고 보수적으로 판단해서 삭제를 할 수 없다. 어떤 메모리가 오랫동안 사용되지 않는다 하더라도 GC는 이 메모리 영역을 해제할 수 없다. 극단적으로 어떤 객체가 백 만년 뒤에 쓰인다면? 이건 구현이 어려워서가 아니라 아예 불가능한 영역이 있다. 미래를 예측할 수 없기 때문이다. GC 구현 기법 중 Generational GC 등이 있는데 이건 접근 불가능한 객체들을 효율적으로 찾기 위한 것이지, 이렇게 더 이상 사용되지 않는, 그런데 도달은 가능한 객체에 대한 누수를 해결하는 것이 아니다. 따라서 어떤 객체로 접근할 수 있는 방법이 있다면 GC는 아무것도 할 수 없고 실제 큰 자바 프로젝트(예를 들어 느려터진 이클립스)에서는 메모리 누수가 많이 일어난다. Managed 환경에서도 메모리 사용을 프로파일링 하는 도구는 많이 있고 메모리 누수 검출 도구도 많이 있다. .NET Memory Profiler, JRockit 같은 것이 일단 있고 C/C++ 쪽은 익히 아는 DevPartner나 GNU 환경에서는 Valgrind 같은 것들이 있다. 위키에도 이런 내용이 잘 있다. 물리적 메모리 누수(lost objects)와 논리적 메모리 누수(useless objects)로 분류하고 GC는 후자에 대해서는 아무것도 할 수 없다. 결론: 가비지 컬렉터가 있어도 메모리 누수는 발생합니다.
Garbage collectors
C
C 에는 가비지 컬렉터가 없다. 하지만 라이브러리 형태로 만들어진 것들이 있다.
- Boehmgc - Boehm garbage collector
See also
- https://en.wikipedia.org/wiki/Garbage_collection_%28computer_science%29 - Garbage_collection(computer_science)
References
<references />