의사 핸들

@codemaru · November 26, 2009 · 3 min read

GetCurrentThread, GetCurrentProcess가 반환하는 핸들 값은 실제 핸들이 아니라 의사핸들이다. 의사핸들이란 실제로 핸들 테이블에 있는 값이 아닌 0xffffffff, 0xfffffffe등과 같이 사전에 정의된 상수를 의미한다. GetCurrentProcess, GetCurrentThread가 하는 일도 단순히 이런 상수 값을 반환하는 역할을 한다. 실제 핸들이 아니기 때문에 핸들 관리를 할 필요가 없고, 사전에 정의된 상수 값이기 때문에 현재 문맥을 빠르게 참조할 수 있는 장점을 가진다. 하지만 이러한 의사 핸들을 사용할 때에는 반드시 자신이 사용하고 있는 핸들이 가짜라는 것을 명심해야 한다. 따라서 의사 핸들 값을 비교하거나 그 값을 저장해놓고 다른 용도로 사용하는 일은 피해야 한다.

이러한 문제점을 보여주는 간단한 코드를 생각해 보자. 아래 코드는 A 스레드의 핸들을 구해서 저장해 놓은 다음 B 스레드에서 그 핸들 값을 다른 프로세스에서 사용하기 위해서 복제하는 간단한 코드다. 별 문제 없어 보이는 이 코드에는 심각한 문제가 있다. 코드를 쓴 개발자의 의도대로 동작하지 않는다는 점이다. 이 코드를 쓴 개발자가 의도했던 바는 A 스레드 핸들을 복제하기 위함이었을 것이다. 하지만 의사 핸들이라는 것 때문에 실제로 복사되는 핸들은 B 스레드의 핸들이 된다.

A 스레드 문맥

PrimaryThread = GetCurrentThread()  

CreateThread B

B 스레드 문맥

DuplicateHandle(PrimaryThread, tmp)

원래 개발자의 의도대로 코드가 동작하도록 만들려면 A 스레드 문맥의 코드를 다음과 같이 고쳐야 한다. 물론 이 경우에 PrimaryThread 핸들이 더 이상 필요하지 않은 시점에 CloseHandle을 통해서 핸들을 닫아 주어야 핸들 누수가 발생하지 않는다.

A 스레드 문맥

PrimaryThread = OpenThread(GetCurrentThreadId())  

CreateThread B
@codemaru
돌아보니 좋은 날도 있었고, 나쁜 날도 있었다. 그런 나의 모든 소소한 일상과 배움을 기록한다. 여기에 기록된 모든 내용은 한 개인의 관점이고 의견이다. 내가 속한 조직과는 1도 상관이 없다.
(C) 2001 YoungJin Shin, 0일째 운영 중