Sleep(0) 과 Sleep(1)
Thread 간 우선순위(Priority) 가 다른 경우에 사용법이 틀려 진다.
1. Sleep(0)
다른 Thread 가 Ready to run 되었다고 해서 자신이 쥐고 있는 CPU의 선점을 풀지 않는다.
Ready to run 되어 있는 Thread 가 지금 선점한 Thread 와 우선순위가 같아야 선점을 푼다.
이 함수를 호출한 스레드가 남은 타임 슬리아스(Time Slace) 를 자동적으로 포기하여 시스템이
다른 스레드를 스케줄 하게 한다. 그런데 시스템에 이 함수를 호출한 스레드와 우선순위가 같거나
그보다 높은 스레드 중에 스케줄 가능 스레드가 없는 경우 Sleep 함수를 호출한 스레드가 다시
스케줄 될 수도 있다.
2. Sleep(1)
Thread 간의 우선순위에 관계없이 다른 Thread 가 Ready to run 상태에 있다면 자신이 쥐고 있던 Thread 선점을 풀고
Ready to run 상태인 Thread 에 CPU 를 넘겨준다.
즉, Context switching 이 이루어 진다.
cf) MSDN
2009년 2월 28일 토요일
일반적인 윈도우 소멸 순서 - WM_CLOSE, WM_DESTORY, WM_QUIT
일반적인 윈도우 소멸 순서 - WM_CLOSE, WM_DESTROY, WM_QUIT
※ WM_SYSCOMMAND → WM_CLOSE → WM_DESTROY → WM_QUIT
1. WM_CLOSE - 윈도우가 닫히기 전에 메시지가 전달 된다.
- 아직 윈도우가 파괴된 것은 아니므로 윈도우가 파괴되는 것을 중간에 제어 할 수 있다.
- 윈도우의 “닫기” 를 누르거나, 키보드의 “Alt + F4”를 눌렀을 경우 발생

- WM_CLOSE 의 핸들러(OnClose) 에서 추가적인 제어를 하지 않는다면 메시지는
DefWindowsProc 로 보내진다.
- CDialog::OnClose() 는 내부적으로 DestroyWindow() 함수를 호출 한다.
- DestroyWindow() 함수는 내부적으로 WM_DESTROY 메시지를 발생 시킨다.
2. DestroyWindow()
- CWnd내부에 있는 윈도우를 destroy 한다.
- 윈도우를 해제하고 입력 포커스를 제거하기 위한 적절한 message를 윈도에게 보낸다.
- 윈도우의 메뉴 제거
- application queue를 비운다.
- timer를 제거
- Clipboard의 소유주 제거
- Clipboard-viewer chain을 끊는다. ( CWnd가 viewer chain의 맨 위에 있을 경우 )
- WM_DESTROY(OnDestroy)와 WM_NCDESTROY(OnNcDestroy) 메시지를 윈도우 에게 보낸다.
하지만 아직 CWnd 객체는 destroy하지 않는다.
3. WM_DESTROY
- Framework이 CWnd에게 현재 CWnd가 소멸되고 있는 중이라고 알려 주기 위하여 호출
- 화면에 윈도우를 숨긴 후 메시지 발생, 아직 윈도우 자체는 파괴되지 않았다
- DestroyWindows() 함수에서 발생 시킨다.
- WM_CREATE 에 반대되는 동작을 수행 한다.
- 차일드 윈도우가 있다면 이 메시지를 차례대로 전달 한다.
- 메인 윈도우에서 PostQuitMessage() 함수를 반드시 호출하여 프로세스의 메시지 루프
를 종료시켜야 한다. 그렇지 않다면 윈도우만 파괴되고 메시지 루프는 계속 실행중인
상태가 되므로 프로세스가 종료되지 않는다.
4. WM_NCDESTROY - Client 영역이 아닌 영역이 Destroy 될 때 Framework 에 의하여 불려짐.
- 윈도우가 소멸될 때 마지막으로 호출되는 메시지
- 핸들러를 재정의 한다면 기본 호출 함수를 가장 위에서 해주자.
5. PostNcDestroy()
- 윈도우가 소멸된 후 OnNcDestroy() 함수에 의해 불려지는 함수
- 사용자들이 상속받아 만든 클래스의 정리를 위한 코드를 넣음.
6. View가 닫혀질 때 호출되는 핸들러 순서
BOOL CAniView::DestroyWindow()
{
// TODO: Add your specialized code here and/or call the base class
// 윈도우가 안보여 지기전에 해야 할 작업 처리
return CView::DestroyWindow();
}
void CAniView::OnDestroy()
{
CView::OnDestroy();
// TODO: Add your message handler code here
}
void CAniView::PostNcDestroy()
{
// TODO: Add your specialized code here and/or call the base class
CView::PostNcDestroy();
}
7. WM_QUIT
- 응용프로그램을 종료 하라는 메시지
- PostQuitMessage() 가 발생 시키는 메시지
- GetMessage() 함수가 0 을 리턴하도록 함으로써 메시지 루프를 종료
- PeekMessage() 함수는 따로 WM_QUIT 메시지를 점검해야 한다.
cf) WM_CLOSE->WM_DESTROY->WM_QUIT :: 윈도우 프로그램의 종료 메시지 순서
※ WM_SYSCOMMAND → WM_CLOSE → WM_DESTROY → WM_QUIT
1. WM_CLOSE - 윈도우가 닫히기 전에 메시지가 전달 된다.
- 아직 윈도우가 파괴된 것은 아니므로 윈도우가 파괴되는 것을 중간에 제어 할 수 있다.
- 윈도우의 “닫기” 를 누르거나, 키보드의 “Alt + F4”를 눌렀을 경우 발생

- WM_CLOSE 의 핸들러(OnClose) 에서 추가적인 제어를 하지 않는다면 메시지는
DefWindowsProc 로 보내진다.
- CDialog::OnClose() 는 내부적으로 DestroyWindow() 함수를 호출 한다.
- DestroyWindow() 함수는 내부적으로 WM_DESTROY 메시지를 발생 시킨다.
2. DestroyWindow()
- CWnd내부에 있는 윈도우를 destroy 한다.
- 윈도우를 해제하고 입력 포커스를 제거하기 위한 적절한 message를 윈도에게 보낸다.
- 윈도우의 메뉴 제거
- application queue를 비운다.
- timer를 제거
- Clipboard의 소유주 제거
- Clipboard-viewer chain을 끊는다. ( CWnd가 viewer chain의 맨 위에 있을 경우 )
- WM_DESTROY(OnDestroy)와 WM_NCDESTROY(OnNcDestroy) 메시지를 윈도우 에게 보낸다.
하지만 아직 CWnd 객체는 destroy하지 않는다.
3. WM_DESTROY
- Framework이 CWnd에게 현재 CWnd가 소멸되고 있는 중이라고 알려 주기 위하여 호출
- 화면에 윈도우를 숨긴 후 메시지 발생, 아직 윈도우 자체는 파괴되지 않았다
- DestroyWindows() 함수에서 발생 시킨다.
- WM_CREATE 에 반대되는 동작을 수행 한다.
- 차일드 윈도우가 있다면 이 메시지를 차례대로 전달 한다.
- 메인 윈도우에서 PostQuitMessage() 함수를 반드시 호출하여 프로세스의 메시지 루프
를 종료시켜야 한다. 그렇지 않다면 윈도우만 파괴되고 메시지 루프는 계속 실행중인
상태가 되므로 프로세스가 종료되지 않는다.
4. WM_NCDESTROY - Client 영역이 아닌 영역이 Destroy 될 때 Framework 에 의하여 불려짐.
- 윈도우가 소멸될 때 마지막으로 호출되는 메시지
- 핸들러를 재정의 한다면 기본 호출 함수를 가장 위에서 해주자.
5. PostNcDestroy()
- 윈도우가 소멸된 후 OnNcDestroy() 함수에 의해 불려지는 함수
- 사용자들이 상속받아 만든 클래스의 정리를 위한 코드를 넣음.
6. View가 닫혀질 때 호출되는 핸들러 순서
BOOL CAniView::DestroyWindow()
{
// TODO: Add your specialized code here and/or call the base class
// 윈도우가 안보여 지기전에 해야 할 작업 처리
return CView::DestroyWindow();
}
void CAniView::OnDestroy()
{
CView::OnDestroy();
// TODO: Add your message handler code here
}
void CAniView::PostNcDestroy()
{
// TODO: Add your specialized code here and/or call the base class
CView::PostNcDestroy();
}
7. WM_QUIT
- 응용프로그램을 종료 하라는 메시지
- PostQuitMessage() 가 발생 시키는 메시지
- GetMessage() 함수가 0 을 리턴하도록 함으로써 메시지 루프를 종료
- PeekMessage() 함수는 따로 WM_QUIT 메시지를 점검해야 한다.
cf) WM_CLOSE->WM_DESTROY->WM_QUIT :: 윈도우 프로그램의 종료 메시지 순서
[VS-] Visual C++ 재배포 가능 패키지

Microsoft Visual C++ 재배포 가능 패키지는 Visual 이 설치되지 않은 컴퓨터에서 Visual C++로 개발된
응용 프로그램을 실행하는 데 필요한 Visual C++ 라이브러리의 런타임 구성 요소를 설치합니다.
응용 프로그램을 실행하는 데 필요한 Visual C++ 라이브러리의 런타임 구성 요소를 설치합니다.
Microsoft Visual C++ 2008 재배포 가능 패키지(x86)
Microsoft Visual C++ 2008 SP1 재배포 가능 패키지(x86)
Microsoft Visual C++ 2008 SP1 재배포 가능 패키지(x64)
2009년 2월 27일 금요일
[ComboBox] 콤보박스 클릭 없이 콤보박스 목록 열기 - CB_SHOWDROPDOWN
콤보박스 클릭 없이 콤보박스 목록 열기 - CB_SHOWDROPDOWN
CB_SHOWDROPDOWN 메시지를 콤보박스에 보내면 된다.
cf) MSDN 에 CB_SHWODROPDOWN 대한 내용. -----------------------------------------------------------
CBS_DROPDOWN 또는 CBS_DROPDOWNLIST 스타일을 가진 콤보박스에서, 목록을 숨기거나 보여주기를 할때
응용프로그램은 CB_SHWODROPDOWN 메시지를 콤보박스에 보낸다.
이 메시지를 보내기 위해서는 SendMessage 를 사용한다. SendMessage 의 파라미터는 아래와 같다.
SendMessage((HWND) hWnd, // 목적 대상 윈도우의 핸들,
CB_SHOWDROPDOWN, // 보내려는 메시지
(WPARAM) wParam, // 보여줄 상태
(LPARAM) lParam, // 사용되지 않는다. 반드시 0 값을 갖는다.
Parameter
wParam
- drop-down 리스트 박스가 보여진 상태인지, 숨겨진 상태인지 지정한다.
TRUE 값이면 리스트 박스를 보여주고, FALSE 값이면 리스트 박스를 숨겨준다.
lParam
- 이 값은 사용되지 않느낟.
Return Value
- 항상 TRUE 를 리턴한다.
Remark
이 메시지는 CBS_SIMPLE 스타일의 콤보박스에는 영향을 끼치지 않는다.
Requirement
Windows NT/2000/XP: Included in Windows NT 3.1 and later.
Windows 95/98/Me: Included in Windows 95 and later.
Header: Declared in Winuser.h; include Windows.h.
--------------------------------------------------------------------------------------------------------
Ex)

메시지 보내기 전

"콤보 열기" 버튼 클릭 메시지로 콤보박스를 열었다.
void CExpandComboDlg::OnBnClickedButton1()
{
m_ComboBox.SendMessage(CB_SHOWDROPDOWN, TRUE, 0);
}
cfile25.uf.1873874150AEC16B0981BA.exe
cf) http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=51&MAEULNO=20&no=8240&page=1
CB_SHOWDROPDOWN 메시지를 콤보박스에 보내면 된다.
cf) MSDN 에 CB_SHWODROPDOWN 대한 내용. -----------------------------------------------------------
CBS_DROPDOWN 또는 CBS_DROPDOWNLIST 스타일을 가진 콤보박스에서, 목록을 숨기거나 보여주기를 할때
응용프로그램은 CB_SHWODROPDOWN 메시지를 콤보박스에 보낸다.
이 메시지를 보내기 위해서는 SendMessage 를 사용한다. SendMessage 의 파라미터는 아래와 같다.
SendMessage((HWND) hWnd, // 목적 대상 윈도우의 핸들,
CB_SHOWDROPDOWN, // 보내려는 메시지
(WPARAM) wParam, // 보여줄 상태
(LPARAM) lParam, // 사용되지 않는다. 반드시 0 값을 갖는다.
Parameter
wParam
- drop-down 리스트 박스가 보여진 상태인지, 숨겨진 상태인지 지정한다.
TRUE 값이면 리스트 박스를 보여주고, FALSE 값이면 리스트 박스를 숨겨준다.
lParam
- 이 값은 사용되지 않느낟.
Return Value
- 항상 TRUE 를 리턴한다.
Remark
이 메시지는 CBS_SIMPLE 스타일의 콤보박스에는 영향을 끼치지 않는다.
Requirement
Windows NT/2000/XP: Included in Windows NT 3.1 and later.
Windows 95/98/Me: Included in Windows 95 and later.
Header: Declared in Winuser.h; include Windows.h.
--------------------------------------------------------------------------------------------------------
Ex)

메시지 보내기 전

"콤보 열기" 버튼 클릭 메시지로 콤보박스를 열었다.
void CExpandComboDlg::OnBnClickedButton1()
{
m_ComboBox.SendMessage(CB_SHOWDROPDOWN, TRUE, 0);
}
cfile25.uf.1873874150AEC16B0981BA.exe
cf) http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=51&MAEULNO=20&no=8240&page=1
2009년 2월 17일 화요일
[ComboBox] ComboBox 이벤트
ComboBox 이벤트
CBN_SELCHANGE : 콤보 박스의 아이템이 변경 되었을 경우
CBS_SHOWDROPDOWN : 콤보 박스의 리스트를 보이거나 숨긴다.
CBN_SELCHANGE : 콤보 박스의 아이템이 변경 되었을 경우
CBS_SHOWDROPDOWN : 콤보 박스의 리스트를 보이거나 숨긴다.
[ComboBox] 현재 선택된 아이템 인덱스 및 텍스트 얻기 - GetCurSel(),GetLBText()
현재 선택된 아이템 인덱스 및 텍스트 얻기 - GetCurSel(), GetLBText()
CComboBox m_ComboStartEvt;
int nIndex = m_ComboStartEvt.GetCurSel();
if (CB_ERR == nIndex)
{
m_DateTimeStartDate.EnableWindow(FALSE);
return;
}
CString sStartEvt = _T("");
m_ComboStartEvt.GetLBText(nIndex, sStartEvt);
BOOL bRetVal = FALSE;
CString sTemp = _T("");
bRetVal = sTemp.LoadString(IDS_FILTERDLG_STARTEVT);
if (0 != sTemp.CompareNoCase(sStartEvt))
m_DateTimeStartDate.EnableWindow();
else
m_DateTimeStartDate.EnableWindow(FALSE);
CComboBox m_ComboStartEvt;
int nIndex = m_ComboStartEvt.GetCurSel();
if (CB_ERR == nIndex)
{
m_DateTimeStartDate.EnableWindow(FALSE);
return;
}
CString sStartEvt = _T("");
m_ComboStartEvt.GetLBText(nIndex, sStartEvt);
BOOL bRetVal = FALSE;
CString sTemp = _T("");
bRetVal = sTemp.LoadString(IDS_FILTERDLG_STARTEVT);
if (0 != sTemp.CompareNoCase(sStartEvt))
m_DateTimeStartDate.EnableWindow();
else
m_DateTimeStartDate.EnableWindow(FALSE);
2009년 2월 16일 월요일
[TreeCtrl] 선택된 아이템의 핸들, 텍스트 얻기
선택된 아이템의 핸들, 텍스트 얻기
CTreeCtrl &TreeCtrl = GetTreeCtrl();
HTREEITEM hTreeItem = TreeCtrl.GetSelectedItem();
if (NULL == hTreeItem)
return _T("");
CString sCurrentItemtext = _T("");
sCurrentItemtext = TreeCtrl.GetItemText(hTreeItem);
return sCurrentItemtext;
CTreeCtrl::GetSelectedItem();
현재 트리에 선택된 아이템의 핸들 얻기
CTreeCtrl::GetItemText(선택된 트리 컨트롤 아이템 핸들);
지정한 핸들에 해당하는 텍스트 얻기
CTreeCtrl &TreeCtrl = GetTreeCtrl();
HTREEITEM hTreeItem = TreeCtrl.GetSelectedItem();
if (NULL == hTreeItem)
return _T("");
CString sCurrentItemtext = _T("");
sCurrentItemtext = TreeCtrl.GetItemText(hTreeItem);
return sCurrentItemtext;
CTreeCtrl::GetSelectedItem();
현재 트리에 선택된 아이템의 핸들 얻기
CTreeCtrl::GetItemText(선택된 트리 컨트롤 아이템 핸들);
지정한 핸들에 해당하는 텍스트 얻기
[ListCtrl] Virtual ListCtrl (가상 리스트 컨트롤) 주의 사항
Virtual ListCtrl (가상 리스트 컨트롤) 주의 사항
요놈을 처음으로 써보는데 생각보다 신경써줄게 많다.
이런 고민사항을 주위에 물어봐도 내가 좀 어렵게 사용하고 있는 듯 한데...
아무튼 나의 시행 착오를 정리하다 보면 나도 쉽게 사용할 수 있게 되겠지.
1. 가상 리스트 뷰의 갱신
GetListCtrl().SetItemCountEx(출력할 아이템의 개수);
2. 가상 리스트뷰 그리기 멈춤, 그리기 시작
GetListCtrl().SetRedraw(FALSE);
GetListCtrl().SetRedraw();
cf) GetListCtrl().SetRedraw(); 동작으로 리스트뷰를 다시 그릴때 헤더도 다시 그리게 된다.
※ 난 이렇게 사용한다.
GetListCtrl().SetRedraw(FALSE);
GetListCtrl().SetItemCountEx(출력할 아이템의 개수);
GetListCtrl().SetRedraw();
Latest Update 09.03.26
요놈을 처음으로 써보는데 생각보다 신경써줄게 많다.
이런 고민사항을 주위에 물어봐도 내가 좀 어렵게 사용하고 있는 듯 한데...
아무튼 나의 시행 착오를 정리하다 보면 나도 쉽게 사용할 수 있게 되겠지.
1. 가상 리스트 뷰의 갱신
GetListCtrl().SetItemCountEx(출력할 아이템의 개수);
2. 가상 리스트뷰 그리기 멈춤, 그리기 시작
GetListCtrl().SetRedraw(FALSE);
GetListCtrl().SetRedraw();
cf) GetListCtrl().SetRedraw(); 동작으로 리스트뷰를 다시 그릴때 헤더도 다시 그리게 된다.
※ 난 이렇게 사용한다.
GetListCtrl().SetRedraw(FALSE);
GetListCtrl().SetItemCountEx(출력할 아이템의 개수);
GetListCtrl().SetRedraw();
Latest Update 09.03.26
2009년 2월 11일 수요일
warning C6011: NULL 포인터 '이름'을(를) 역참조하고 있습니다.
warning C6011: NULL 포인터 '이름'을(를) 역참조하고 있습니다.
VS2008 의 "코드 분석" 을 하면 볼 수 있는 경고 메시지 이다.
※ 메시지가 발생한 코드
INT nIndex = 0;
INT nItemCount = m_EvtFindList.GetCount();
POSITION pos = m_EvtFindList.GetHeadPosition();
CEvtFind *pEvtFind = NULL;
for (nIndex = 0; nIndex < nItemCount; nIndex++)
{
pEvtFind = reinterpret_cast<CEvtFind *>(m_EvtFindList.GetNext(pos));
if (0 == _rsLogName.CompareNoCase(pEvtFind->GetLogName()))
break;
if (nIndex == nItemCount - 1)
return _T("");
}
return pEvtFind->GetRangeName();
코드를 보면 pEvtFind 변수가 NULL로 초기화 되어 있다.
for 반복문에서 pEvtFind 값이 설정이 되고 return 문에서 pEvtFind 를 사용하고 있다.
코드를 작성할 때는 당연히 pEvtFind 값이 for 문을 나오면 NULL 포인터가 아님을 확신하고 작성하였다.
하지만 컴파일러는 for() 문에서 바로 빠져 나오면 return 문에서 NULL 값을 가진 pEvtFind 사용할 수 있음을 경고 하는
것이다.
경고를 없애기 위해 다음과 같이 코딩 해 주었다.
INT nIndex = 0;
INT nItemCount = m_EvtFindList.GetCount();
POSITION pos = m_EvtFindList.GetHeadPosition();
CEvtFind *pEvtFind = NULL;
for (nIndex = 0; nIndex < nItemCount; nIndex++)
{
pEvtFind = reinterpret_cast<CEvtFind *>(m_EvtFindList.GetNext(pos));
if (0 == _rsLogName.CompareNoCase(pEvtFind->GetLogName()))
break;
if (nIndex == nItemCount - 1)
return _T("");
}
if (NULL == pEvtFind)
return _T("");
return pEvtFind->GetRangeName();
cf) http://msdn.microsoft.com/ko-kr/library/2ayc37ac.aspx
VS2008 의 "코드 분석" 을 하면 볼 수 있는 경고 메시지 이다.
※ 메시지가 발생한 코드
INT nIndex = 0;
INT nItemCount = m_EvtFindList.GetCount();
POSITION pos = m_EvtFindList.GetHeadPosition();
CEvtFind *pEvtFind = NULL;
for (nIndex = 0; nIndex < nItemCount; nIndex++)
{
pEvtFind = reinterpret_cast<CEvtFind *>(m_EvtFindList.GetNext(pos));
if (0 == _rsLogName.CompareNoCase(pEvtFind->GetLogName()))
break;
if (nIndex == nItemCount - 1)
return _T("");
}
return pEvtFind->GetRangeName();
코드를 보면 pEvtFind 변수가 NULL로 초기화 되어 있다.
for 반복문에서 pEvtFind 값이 설정이 되고 return 문에서 pEvtFind 를 사용하고 있다.
코드를 작성할 때는 당연히 pEvtFind 값이 for 문을 나오면 NULL 포인터가 아님을 확신하고 작성하였다.
하지만 컴파일러는 for() 문에서 바로 빠져 나오면 return 문에서 NULL 값을 가진 pEvtFind 사용할 수 있음을 경고 하는
것이다.
경고를 없애기 위해 다음과 같이 코딩 해 주었다.
INT nIndex = 0;
INT nItemCount = m_EvtFindList.GetCount();
POSITION pos = m_EvtFindList.GetHeadPosition();
CEvtFind *pEvtFind = NULL;
for (nIndex = 0; nIndex < nItemCount; nIndex++)
{
pEvtFind = reinterpret_cast<CEvtFind *>(m_EvtFindList.GetNext(pos));
if (0 == _rsLogName.CompareNoCase(pEvtFind->GetLogName()))
break;
if (nIndex == nItemCount - 1)
return _T("");
}
if (NULL == pEvtFind)
return _T("");
return pEvtFind->GetRangeName();
cf) http://msdn.microsoft.com/ko-kr/library/2ayc37ac.aspx
2009년 2월 8일 일요일
Kernel Object (커널 오브젝트)
Kernel Object (커널 오브젝트)
cf) Windows 기반 에서만 적용되는 개념
1. System Resource (시스템 리소스)
- 우리가 사용하고자 하는 시스템의 자원이다. (파일, 스레드, 프로세스, 뮤텍스...)
- 시스템 리소스는 OS(정확히는 Kernel)가 생성 및 유지, 관리 한다.
cf) 프로그래밍 시 로그파일을 만들기 위해선, 커널에게 ‘파일’ 이라는 시스템 리소스를 생성
하라고 부탁한다.
2. Kernel Object (커널 오브젝트)
- 시스템 리소스인 파일을 생성 했다면, 이제 그 파일을 유지 및, 관리 해야 한다.
파일은 시스템 리소스 이기 때문에 kernel 이 유지 관리 한다.
유지, 관리를 하기 위해서 kernel 은 Kernel Object 라는 것을 만든다.
- Kernel Object 는 시스템 리소스를 유지 관리하기 위한 데이터 블록 이다. (C구조체 유사)
- 시스템 리소스마다 유지해야 하는 정보가 다르기 때문에 각각 다른 데이터 블록 형태를 갖음
Cf). 프로그램의 기본 실행 단위 : Linux -> Process
Windows -> Thread
Cf). Windows 프로그램의 실행
Process 실행 -> Main Thread 생성 (무조건 생성 된다.)
Main Thread (CRT 함수) 가 main 함수를 실행 시킨다.
3. System Resource, Kernel Object, Handle 과의 관계
Ex) System Resource 의 생성 (파일)

- Kernel 이 시스템 리소스인 파일을 생성 한다.
- Kernel 은 파일을 유지, 관리 하기 위해 파일에 대한 Kernel Object 를 생성 한다.
- Kernel 은 Kernel Object 를 가리키는 Handle을 리턴해 준다.
- 즉, 우리는 Handle 을 통해서 Kernel Object 에 접근 하는 것이고,
Kernel Object가 System Resource 에 접근 하게 되는 것이다.
Ex) System Resource 의 유지, 관리

4. 프로세스의 Kernel Object Handle Table
- 프로세스가 초기화 되면 운영체제는 프로세스를 위해 Kernel Object Handle Table 을
5. 프로세스가 핸들 테이블을 다루는 방법
last update 09.02.10
cf) Windows 기반 에서만 적용되는 개념
1. System Resource (시스템 리소스)
- 우리가 사용하고자 하는 시스템의 자원이다. (파일, 스레드, 프로세스, 뮤텍스...)
- 시스템 리소스는 OS(정확히는 Kernel)가 생성 및 유지, 관리 한다.
cf) 프로그래밍 시 로그파일을 만들기 위해선, 커널에게 ‘파일’ 이라는 시스템 리소스를 생성
하라고 부탁한다.
2. Kernel Object (커널 오브젝트)
- 시스템 리소스인 파일을 생성 했다면, 이제 그 파일을 유지 및, 관리 해야 한다.
파일은 시스템 리소스 이기 때문에 kernel 이 유지 관리 한다.
유지, 관리를 하기 위해서 kernel 은 Kernel Object 라는 것을 만든다.
- Kernel Object 는 시스템 리소스를 유지 관리하기 위한 데이터 블록 이다. (C구조체 유사)
- 시스템 리소스마다 유지해야 하는 정보가 다르기 때문에 각각 다른 데이터 블록 형태를 갖음
Cf). 프로그램의 기본 실행 단위 : Linux -> Process
Windows -> Thread
Cf). Windows 프로그램의 실행
Process 실행 -> Main Thread 생성 (무조건 생성 된다.)
Main Thread (CRT 함수) 가 main 함수를 실행 시킨다.
3. System Resource, Kernel Object, Handle 과의 관계
Ex) System Resource 의 생성 (파일)

- Kernel 이 시스템 리소스인 파일을 생성 한다.
- Kernel 은 파일을 유지, 관리 하기 위해 파일에 대한 Kernel Object 를 생성 한다.
- Kernel 은 Kernel Object 를 가리키는 Handle을 리턴해 준다.
- 즉, 우리는 Handle 을 통해서 Kernel Object 에 접근 하는 것이고,
Kernel Object가 System Resource 에 접근 하게 되는 것이다.
Ex) System Resource 의 유지, 관리

- Handle 을 통해 Kernel Object 에 접근한다.
Kernel Object 는 파일을 관리하는 여러 데이터를 이용해 파일을 관리 한다.
4. 프로세스의 Kernel Object Handle Table
- 프로세스가 초기화 되면 운영체제는 프로세스를 위해 Kernel Object Handle Table 을
할당 한다. (각각의 프로세스 마다)
- 이 핸들 테이블은 User Object 나 GDI Object 에 의해서는 사용되지 않고 오직,
- 이 핸들 테이블은 User Object 나 GDI Object 에 의해서는 사용되지 않고 오직,
Kernel Object 만을 위해 사용 한다.
cf). windows application 프로그래밍시 사용하게 되는 Object
- Kernel Object : 파일, 프로세스, 스레드, 세마포어...
- User Object : 윈도우, 커서, 캐럿...
- GDI Object : 팬, 브러시, 폰트, 비트맵...
- 새로운 프로세스가 생성 되면, 프로세스의 핸들 테이블이 생성이 되고, 테이블은 비어있다.
cf). windows application 프로그래밍시 사용하게 되는 Object
- Kernel Object : 파일, 프로세스, 스레드, 세마포어...
- User Object : 윈도우, 커서, 캐럿...
- GDI Object : 팬, 브러시, 폰트, 비트맵...
- 새로운 프로세스가 생성 되면, 프로세스의 핸들 테이블이 생성이 되고, 테이블은 비어있다.
5. 프로세스가 핸들 테이블을 다루는 방법
- 프로세스가 초기화 되면 자신의 Program 영역에 비어있는 커널 오브젝트 객체 테이블을 생성한다.
- 프로세스가 시스템 리소스를 사용하기 위해 커널에 요청하면 커널은 커널 영역에 리소스를 생성하고
커널 오브젝트를 생성 한다.
- 커널 오브젝트를 가리키는 주소는 프로세스의 커널 오브젝트 핸들 테이블에 기록이 되고, 핸들 테이블에
있는 핸들 값을 리턴해 주게 된다.
- 프로세스가 시스템 리소스를 사용하기 위해 커널에 요청하면 커널은 커널 영역에 리소스를 생성하고
커널 오브젝트를 생성 한다.
- 커널 오브젝트를 가리키는 주소는 프로세스의 커널 오브젝트 핸들 테이블에 기록이 되고, 핸들 테이블에
있는 핸들 값을 리턴해 주게 된다.
- 프로세스가 리소스 사용을 마쳤으면 CloseHandle() 함수를 호출 하게 된다.
- 함수는 호출이 리터되기 직전에 커널 오브젝트 핸들 테이블을 참조하여 핸들 값으로 커널 오브젝트에
접근한다. 커널 오브젝트 내에 카운트 값을 1 감소 시킨다.
- 커널 오브젝트의 카운트 값이 0 이 되면 커널은 커널 오브젝트를 메모리 해제 시킨다.
- 커널 오브젝트 핸들 테이블에서 해당 커널 오브젝트 값을 삭제 한다.
- 함수는 호출이 리터되기 직전에 커널 오브젝트 핸들 테이블을 참조하여 핸들 값으로 커널 오브젝트에
접근한다. 커널 오브젝트 내에 카운트 값을 1 감소 시킨다.
- 커널 오브젝트의 카운트 값이 0 이 되면 커널은 커널 오브젝트를 메모리 해제 시킨다.
- 커널 오브젝트 핸들 테이블에서 해당 커널 오브젝트 값을 삭제 한다.
last update 09.02.10
2009년 2월 4일 수요일
사용자 정의 함수를 통한 에러 내용 전달 - _set_invalid_parameter_handler
사용자 정의 함수를 통한 에러 내용 전달
C 런타임 라이브러리는 인자의 유효성 검증이 실패하였을 경우 사용자가 정의한 함수를 통해
에러 내용을 전달할 수 있는 기능을 제공하고 있다. 이러한 함수를 이용하면 에러를 기록하거나
디버거를 기동하는 등의 사용자 작업을 수행할 수 있다.
■ 사용 단계
1. 사용할 함수의 원형을 작성한다.
void InvalidParameterHandler(PCTSTR expression,
PCTSTR function,
PCTSTR file,
unsigned int line,
uintptr_t pReserved);
expression : C런타임 함수 내에서 발생한 테스트 실패에 대한 설명 문자열 전달
function : 함수 이름
file : 소스 파일 명
line : 에러가 발생한 소스코드의 행 번호
pReserved : 예약어
2. _set_invalid_parameter_handler 를 호출하여 앞서 작성한 함수를 등록
3. _CrtSetReportMode(_CRT_ASSERT, 0) 을 어플리케이션 시작 시점에 호출하여 C런타임 Assertion 다이얼로그 박스가
나타나지 않도록 한다.
_CrtSetReportMode(_CRT_ASSERT, 0);
4. String.h 에 정의된 기존 문자열 함수를 대처하는 안전 문자열 함수들을 사용
호출한 함수가 정상 수행되었는지의 여부를 확인하려면 반환되는 errno_t 값을 확인하면 됨.
S_OK 가 반환 되면 함수가성공한 것임.
그 외에 다른 값은 errno.h 에 정의되어 있음.
■ 예제 소스
#include "stdafx.h"
#include <Windows.h> /**< Using Windows Data Type */
#include <crtdbg.h> /**< Using _CrtReportMode() Option */
void InvalidParameterHandler(PCTSTR expression, PCTSTR function, PCTSTR file,
unsigned int line, uintptr_t pReserved);
int _tmain(int argc, _TCHAR* argv[])
{
TCHAR szBefore[5] = {_T('B'), _T('B'), _T('B'), _T('B'), _T('\0')};
TCHAR szBuffer[10] = {_T('-'), _T('-'), _T('-'), _T('-'), _T('-'),
_T('-'), _T('-'), _T('-'), _T('-'), _T('\0')};
TCHAR szAfter[5] = {_T('A'), _T('A'), _T('A'), _T('A'), _T('\0')};
errno_t result = 0;
/**< CRT가 Assertion 다이얼 로그를 출력하지 못하게 함 */
_CrtSetReportMode(_CRT_ASSERT, 0);
/**< 사용자 정의 핸들러 등록 */
_invalid_parameter_handler newHandler = InvalidParameterHandler;
_invalid_parameter_handler oldHandler = _set_invalid_parameter_handler(newHandler);
/**< CRT 함수 실패 소스 */
result = _tcscpy_s(szBuffer, _countof(szBuffer), _T("0123456789"));
/**< CRT 의 기본 핸들러 복원 */
_set_invalid_parameter_handler(oldHandler);
return EXIT_SUCCESS;
}
/*
@param
[in] expression : CRT 함수 내에서 발생한 테스트 실패에 대한 설명 문자열
[in] function : 실패를 발생시킨 CRT 함수 이름
[in] file : 소스 파일 이름 [in] line : 에러가 발생한 소스 코드의 행 번호
[out] pReserved : 예약어
@return void
@note 사용자 정의한 유효 파라미터 핸들러
@note 이 핸들러는 CRT가 유효 파라미터 검사를 수행할 때 기본 핸들러 대신 수행
*/
void InvalidParameterHandler(PCTSTR expression, PCTSTR function, PCTSTR file,
unsigned int line, uintptr_t pReserved)
{
wprintf(_T("Invalid parameter detected in function %s.\n"), function);
wprintf(_T("File: %s Line: %d\n"), file, line);
wprintf(_T("Expression: %s\n"), expression);
exit(EXIT_FAILURE);
}
■ 출력 예

cfile9.uf.11183D3350AEC1680AC1A1.zip
cf) MSDN, WINDOWS VIA C/C++ - 한빛 미디어
C 런타임 라이브러리는 인자의 유효성 검증이 실패하였을 경우 사용자가 정의한 함수를 통해
에러 내용을 전달할 수 있는 기능을 제공하고 있다. 이러한 함수를 이용하면 에러를 기록하거나
디버거를 기동하는 등의 사용자 작업을 수행할 수 있다.
■ 사용 단계
1. 사용할 함수의 원형을 작성한다.
void InvalidParameterHandler(PCTSTR expression,
PCTSTR function,
PCTSTR file,
unsigned int line,
uintptr_t pReserved);
expression : C런타임 함수 내에서 발생한 테스트 실패에 대한 설명 문자열 전달
function : 함수 이름
file : 소스 파일 명
line : 에러가 발생한 소스코드의 행 번호
pReserved : 예약어
2. _set_invalid_parameter_handler 를 호출하여 앞서 작성한 함수를 등록
_invalid_parameter_handler newHandler = InvalidParameterHandler; |
3. _CrtSetReportMode(_CRT_ASSERT, 0) 을 어플리케이션 시작 시점에 호출하여 C런타임 Assertion 다이얼로그 박스가
나타나지 않도록 한다.
_CrtSetReportMode(_CRT_ASSERT, 0);
4. String.h 에 정의된 기존 문자열 함수를 대처하는 안전 문자열 함수들을 사용
호출한 함수가 정상 수행되었는지의 여부를 확인하려면 반환되는 errno_t 값을 확인하면 됨.
S_OK 가 반환 되면 함수가성공한 것임.
그 외에 다른 값은 errno.h 에 정의되어 있음.
■ 예제 소스
#include "stdafx.h"
#include <Windows.h> /**< Using Windows Data Type */
#include <crtdbg.h> /**< Using _CrtReportMode() Option */
void InvalidParameterHandler(PCTSTR expression, PCTSTR function, PCTSTR file,
unsigned int line, uintptr_t pReserved);
int _tmain(int argc, _TCHAR* argv[])
{
TCHAR szBefore[5] = {_T('B'), _T('B'), _T('B'), _T('B'), _T('\0')};
TCHAR szBuffer[10] = {_T('-'), _T('-'), _T('-'), _T('-'), _T('-'),
_T('-'), _T('-'), _T('-'), _T('-'), _T('\0')};
TCHAR szAfter[5] = {_T('A'), _T('A'), _T('A'), _T('A'), _T('\0')};
errno_t result = 0;
/**< CRT가 Assertion 다이얼 로그를 출력하지 못하게 함 */
_CrtSetReportMode(_CRT_ASSERT, 0);
/**< 사용자 정의 핸들러 등록 */
_invalid_parameter_handler newHandler = InvalidParameterHandler;
_invalid_parameter_handler oldHandler = _set_invalid_parameter_handler(newHandler);
/**< CRT 함수 실패 소스 */
result = _tcscpy_s(szBuffer, _countof(szBuffer), _T("0123456789"));
/**< CRT 의 기본 핸들러 복원 */
_set_invalid_parameter_handler(oldHandler);
return EXIT_SUCCESS;
}
/*
@param
[in] expression : CRT 함수 내에서 발생한 테스트 실패에 대한 설명 문자열
[in] function : 실패를 발생시킨 CRT 함수 이름
[in] file : 소스 파일 이름 [in] line : 에러가 발생한 소스 코드의 행 번호
[out] pReserved : 예약어
@return void
@note 사용자 정의한 유효 파라미터 핸들러
@note 이 핸들러는 CRT가 유효 파라미터 검사를 수행할 때 기본 핸들러 대신 수행
*/
void InvalidParameterHandler(PCTSTR expression, PCTSTR function, PCTSTR file,
unsigned int line, uintptr_t pReserved)
{
wprintf(_T("Invalid parameter detected in function %s.\n"), function);
wprintf(_T("File: %s Line: %d\n"), file, line);
wprintf(_T("Expression: %s\n"), expression);
exit(EXIT_FAILURE);
}
■ 출력 예

cfile9.uf.11183D3350AEC1680AC1A1.zip
cf) MSDN, WINDOWS VIA C/C++ - 한빛 미디어
2009년 2월 3일 화요일
About Unicode (유니코드)
About Unicode
■ 문자 인코딩 (Character encoding)
문자들의 집합을 컴퓨터에 저장하거나 통신에 사용할 목적으로 부호화 하는 방법.
ex). 모스 부호
라틴, 알파벳, 숫자, 특수문자 → 정수 및 7bit 이진수 로 변환 (ASCII 문자열 셋트)
■ 문자 집합(Character set, charset)
문자 집합(문자 셋) 은 정보를 표현하기 위해 글자들의 집합을 정의 한 것
ex) ASCII 문자열 셋
※ 일반적으로 "어떤 문자를 사용할 수 있으며, 어떤 식으로 표현 되는지를 나타낸다는데" 있어서의 의미로
"문자 집합" = "문자 인코딩" 동의어로 취급 되기도 함.
■ 문자 집합의 변화ANSI → DBCS → Unicode
1. ANSI 문자 - ASCII 코드 (문자열 셋) 을 사용.
- 하나의 문자를 표현 하는데 1Byte 를 사용.
- 문자열의 끝이 0 으로 끝나는 1Byte 문자.
- 1Byte 는 256 가지 문자를 표현
※ 문제점
- 전세계의 모든 문자를 1Byte 로 표현할 수 없음.
2. DBCS (Double Byte Character Set)
- 하나의 문자를 표현 하는데 1Byte 또는 2Byte 사용. (즉, 고정된 크기로 표현하지 않음)
- ex). 일본의 간지의 경우, 첫번째 문자가 0x81 ~ 0x9F 또는 0xE0 ~ 0xFC 범위 안에 있으면
하나의 문자를 결정 짓기 위해 그 다음 Byte 까지 확인 해야 한다.
※ 문제점
- 하나의 문자를 표현 하는데 어떤 경우는 1Byte, 어떤 경우는 2Byte 로 표현 된다는 것은
인코딩 방법에 있어 불편함을 초래 한다.
※ 윈도우 함수와 C 런타임 라이브러리 함수는 더이상 DBCS를 지원하지 않는다.
3. Unicode
- 전세계 모든 문자를 컴퓨터에서 표현할 수 있도록 만든 정수 테이블
- 유니코드의 재정 의도
- 기존의 인코딩 등른 그 규모나 범위 면에서 한정되어 있고, 다국어 환경 에서는 서로 호환되지 않는 문제점 갖는다.
- 현존하는 문자 인코딩 방법들을 모두 유니코드로 교체 하는 것.
- 유니코드 에는 "문자집합 + 문자 인코딩 + 문자 정보 데이터 베이스 + 문자를 다루기 위한 알고리즘" 이 포함되어 있다.
■ Unicode 를 이용한 문자 인코딩 방법
1. UTF-8
- 하나의 문자를 나타내기 위해 1, 2, 3, 4Byte 로 인코딩을 수행
- 문자가 0x0080 미만에 있다면 해당 문자는 1Byte 로 인코딩 됨. (영어 문자 인코딩의 최적)
- 문자가 0x0080 ~ 0x07FF 범위에 있다면 2Byte 로 인코딩 됨. (유럽 및 중동의 언어에 최적)
- 문자가 0x0800 이상의 문자들은 3Byte 로 인코딩 됨. (주로 동아시아 언어에 최적)
- 그 외에는 4Byte 로 인코딩 됨.
- 일반적인 인코딩 방법 이지만 0x0800 이상의 문자를 많이 사용할 경우 비효율적 이다.
2. UTF-16 - Wide Character 라고 불리기도 함.
- 각 문자를 2Byte 로 인코딩 함.
- 전세계의 대부분의 언어가 16bit (2Byte) 로 표현이 가능 하기 때문에 Windows 는 UTF-16을 사용. (Windows Vista 역시)
- 몇몇 소수 언어들은 16bit 로 표현하기 충분하지 않기때문에 UTF-16 에 대응하는 32bit 인코딩 방법도 존재
- UTF-16 은 공간 절약과 코딩의 편의성 사이의 적절한 절충안
- .Net 프레임워크의 경우 모든 문자를 UTF-16 으로 인코딩 함.
3. UTF-32
- 모든 문자를 4Byte 로 인코딩 함.
- 모든 언어에 대해 문자 변환 알고리즘을 간단히 구성하려 할 때나 가변 길이의 인코딩 방식을 사용하고 싶지 않은 경우에
유용.
- UTF-32 를 사용하면 모든 문자가 4Byte 이므로 다른 대안에 대해 고려할 필요가 없다.
- 메모리 사용에 있어 매우 비효율적인 인코딩 방식.
- 파일 저장 방식이나, 네트워크를 통한 전송 방식으로는 거의 사용되지 않음.
- 보통 프로그램 내부에서만 사용
cf) Windows VIA C/C++ - 한빛 미디어, 위키백과
■ 문자 인코딩 (Character encoding)
문자들의 집합을 컴퓨터에 저장하거나 통신에 사용할 목적으로 부호화 하는 방법.
ex). 모스 부호
라틴, 알파벳, 숫자, 특수문자 → 정수 및 7bit 이진수 로 변환 (ASCII 문자열 셋트)
■ 문자 집합(Character set, charset)
문자 집합(문자 셋) 은 정보를 표현하기 위해 글자들의 집합을 정의 한 것
ex) ASCII 문자열 셋
※ 일반적으로 "어떤 문자를 사용할 수 있으며, 어떤 식으로 표현 되는지를 나타낸다는데" 있어서의 의미로
"문자 집합" = "문자 인코딩" 동의어로 취급 되기도 함.
■ 문자 집합의 변화ANSI → DBCS → Unicode
1. ANSI 문자 - ASCII 코드 (문자열 셋) 을 사용.
- 하나의 문자를 표현 하는데 1Byte 를 사용.
- 문자열의 끝이 0 으로 끝나는 1Byte 문자.
- 1Byte 는 256 가지 문자를 표현
※ 문제점
- 전세계의 모든 문자를 1Byte 로 표현할 수 없음.
2. DBCS (Double Byte Character Set)
- 하나의 문자를 표현 하는데 1Byte 또는 2Byte 사용. (즉, 고정된 크기로 표현하지 않음)
- ex). 일본의 간지의 경우, 첫번째 문자가 0x81 ~ 0x9F 또는 0xE0 ~ 0xFC 범위 안에 있으면
하나의 문자를 결정 짓기 위해 그 다음 Byte 까지 확인 해야 한다.
※ 문제점
- 하나의 문자를 표현 하는데 어떤 경우는 1Byte, 어떤 경우는 2Byte 로 표현 된다는 것은
인코딩 방법에 있어 불편함을 초래 한다.
※ 윈도우 함수와 C 런타임 라이브러리 함수는 더이상 DBCS를 지원하지 않는다.
3. Unicode
- 전세계 모든 문자를 컴퓨터에서 표현할 수 있도록 만든 정수 테이블
- 유니코드의 재정 의도
- 기존의 인코딩 등른 그 규모나 범위 면에서 한정되어 있고, 다국어 환경 에서는 서로 호환되지 않는 문제점 갖는다.
- 현존하는 문자 인코딩 방법들을 모두 유니코드로 교체 하는 것.
- 유니코드 에는 "문자집합 + 문자 인코딩 + 문자 정보 데이터 베이스 + 문자를 다루기 위한 알고리즘" 이 포함되어 있다.
■ Unicode 를 이용한 문자 인코딩 방법
1. UTF-8
- 하나의 문자를 나타내기 위해 1, 2, 3, 4Byte 로 인코딩을 수행
- 문자가 0x0080 미만에 있다면 해당 문자는 1Byte 로 인코딩 됨. (영어 문자 인코딩의 최적)
- 문자가 0x0080 ~ 0x07FF 범위에 있다면 2Byte 로 인코딩 됨. (유럽 및 중동의 언어에 최적)
- 문자가 0x0800 이상의 문자들은 3Byte 로 인코딩 됨. (주로 동아시아 언어에 최적)
- 그 외에는 4Byte 로 인코딩 됨.
- 일반적인 인코딩 방법 이지만 0x0800 이상의 문자를 많이 사용할 경우 비효율적 이다.
2. UTF-16 - Wide Character 라고 불리기도 함.
- 각 문자를 2Byte 로 인코딩 함.
- 전세계의 대부분의 언어가 16bit (2Byte) 로 표현이 가능 하기 때문에 Windows 는 UTF-16을 사용. (Windows Vista 역시)
- 몇몇 소수 언어들은 16bit 로 표현하기 충분하지 않기때문에 UTF-16 에 대응하는 32bit 인코딩 방법도 존재
- UTF-16 은 공간 절약과 코딩의 편의성 사이의 적절한 절충안
- .Net 프레임워크의 경우 모든 문자를 UTF-16 으로 인코딩 함.
3. UTF-32
- 모든 문자를 4Byte 로 인코딩 함.
- 모든 언어에 대해 문자 변환 알고리즘을 간단히 구성하려 할 때나 가변 길이의 인코딩 방식을 사용하고 싶지 않은 경우에
유용.
- UTF-32 를 사용하면 모든 문자가 4Byte 이므로 다른 대안에 대해 고려할 필요가 없다.
- 메모리 사용에 있어 매우 비효율적인 인코딩 방식.
- 파일 저장 방식이나, 네트워크를 통한 전송 방식으로는 거의 사용되지 않음.
- 보통 프로그램 내부에서만 사용
cf) Windows VIA C/C++ - 한빛 미디어, 위키백과
2009년 2월 2일 월요일
[ListCtrl] 특정 열(Row) 로 화면 이동 - EnsureVisible()
특정 열(Row) 로 화면 이동
GetListCtrl().EnsureVisible(리스트 인덱스, TRUE);
GetListCtrl().EnsureVisible(리스트 인덱스, TRUE);
피드 구독하기:
글 (Atom)