시작 전 소개

뇌를 자극하는 윈도우즈 프로그래밍
1챕터 정리본 바로가기
2챕터 정리본 바로가기
3챕터 정리본 바로가기
4챕터 세션1 정리본
4챕터 세션 2 정리본
5챕터 세션 1-2-3 정리본
5챕터 세션 4-5 정리본
6챕터 세션1
6챕터 세션2

커널 오브젝트와 Usage Count

여러번 강조한 내용이지만, 커널 오브젝트는 운영체제에게 종속적이기 때문에, 소멸시킬 권한 역시 운영체제에게 있다.

CloseHandler

프로세스가 생성되면 커널 오브젝트는 생성된다.
그러나, 커널 오브젝트의 소멸은 프로세스의 소멸 시점과 항상 일치하지는 않는다.
즉 프로세스가 소멸한다고 해도 커널 오브젝트는 존재하는 경우가 있을 수 있다는 것이다.
그래서 우리는 메모리의 누수를 막기 위해 운영체제에게 Cloase Handle을 사용하여 커널 오브젝트의 소멸 시점을 명시하여준다.

프로세스의 소멸

예제 코드를 통해 우리가 CloseHandle로 소멸을 요청하더라도, 프로세스가 소멸되지 않는 경우가 있음을 확인했다.
즉 createProcess는 우리가 요구를 넣으면 운영체제가 바로 프로세스를 만드는 데에 비해, CloseHandle을 통해 핸들을 닫는다고 해도 프로세스의 종료와 연결시키기는 어렵다는 뜻이다.

프로세스 종료 코드

우리는 습관적으로 메인함수의 끝에 return 0을 붙인다.
바로 이 세션에서 말하는 종료코드가 이 return 0이다.

6-6 예제

우선 몇가지 실험을 해보았다.
CloseHandle을 일부로 하지 않는 실험을 해보면 메모리 누수에 대한 경고가 뜬다.

msdn 자식 프로세스 대기

DWORD WaitForSingleObject(
  대기하려는 프로세스의 핸들정보,
  [in] DWORD  dwMilliseconds(시간세팅)
  //INFINITE로 설정시 무한대기에 돌입한다고 이해하면됨
);

만약 에러코드 나처럼 에러코드 2가 뜬다면 실행 파일에 문제가 생겼을 가능성이 크다.
예를 들어 백신의 실시간 검사로 인해 파일이 손상되었다거나, exe파일의 비트수를 잘못맞추었다거나 하는 등의 경우가 있다.
나의 경우 x86으로 자식을 빌드해놓고, 이 자식 프로세스를 실행시키는 부모 프로세스의 비트수를 다르게 설정하여 에러가 뜨게 되었다.

종료코드 설정 활용

return 0을 사용하면 프로그램의 종료 여부는 확인 가능하지만, 정확한 종료 상태에 대해 파악을 하기는 어려울 수 있다.
중간에 문제가 있어서 종료가 되었든, 정상적인 종료든 0을 반환시키기 때문이다.
또한 비정상적 종료 상황을 세분화하여 프로세스의 생성자체를 실패한 경우 200 출력 실패시 100등을 종료코드로 설정하는 것도 가능하다.

Usage Count

자식 프로세스의 종료 코드는자식 프로세스의 커널 오브젝트에저장된다.

또한 이 커널 오브젝트는 프로세스 소멸 시 자동으로 소멸되지 않는다.
그렇다면 커널 오브젝트는 언제 소멸이 되어야 부모프로세스에서도 종료코드를 얻을 수 있을까?
부모 프로세스가 자식 프로세스의 참조를 하지 않을 때에 소멸을 시키면 된다.

Count 세기

Usage Count는 0부터 시작하는 것이 아니라, 생성과 동시에 1부터 시작한다.
생성 시 0으로 시작하면 windows가 참조하는 프로세스가 없다고 인식하여 커널 오브젝트를 소멸시킬 수도 있기 때문이다.
따라서 접근 대상이 늘어날 때마다 Usage Count가 늘어나며, 이는 접근 가능한 핸들의 숫자도 증가하였음을 의미한다.

예제의 Count세기
[단계1]오브젝트의 UsageCount는 생성 즉시 1로 시작된다.
[단계2]이때 부모 프로세스는 커널 오브젝트를 참고해야하므로 1이 증가한 채로 시작된다.-즉 2개
[단계3]자식 프로세스가 종료코드를 출력하게되면, 자식프로세스는 더이상 참조하지 않기 때문에 UsageCount는 1로 변한다.
[단계4]부모 프로세스가 CloseHandle을 호출하면 UsageCount는 한개 더 줄어 0으로 변한다.

완전 소멸

CloseHandle을 호출하면 Usage Count는 1개 줄어들게 된다.
여기에서 1개 줄어든다는 설명이 중요한 이유는 여러개의 핸들이 존재하는 경우도 있기 때문이다.
또한 CloseHandle Count를 1개 줄여 0으로 만들 수도 있지만, 꼭 이 함수의 호출이 커널 오브젝트의 완전 삭제를 의미하는 것은 아니다.

문제의 정답

왜 익스플로어 실행시 UsageCount는 2개가 되어야할까?
저자의 설명에 따르면 강제로 프로세스를 종료하면 바탕화면의 아이콘들이 전부 사라졌다는 말이 나온다.
이로 미루어보아 익스플로어가 실행되기 위해서Count1개+ 바탕화면이 익스플로어를 참조해서 생기는 Count(ui관련 추정)1개가 Count되었음을 알 수 다.

참조 링크

메모리 누수란

댓글남기기