정리

boost 관련 참고할만한 링크

저장소/VC++


boost 스마트 포인터 파헤치기 : http://blog.naver.com/sorkelf/40132656978

흥배님의 다양한 boost 예제 : http://jacking75.cafe24.com/Boost/libraries.htm

boost 입문 : http://mech12.springnote.com/pages/690403


deprecated 설정

저장소/VC++
deprecated : 중요도가 떨어져 더 이상 사용되지 않고 앞으로는 사라지게 될(신조어) - by 네이버 영어사전


[Visual C++ Language Reference]

How to use:
__declspec(deprecated) or __declspec(deprecated("do not use"))

(Microsoft specific) With the exceptions noted below, the deprecated declaration offers the same functionality as the deprecated pragma:

  • The deprecated declaration lets you specify particular forms of function overloads as deprecated, whereas the pragma form applies to all overloaded forms of a function name.

  • The deprecated declaration lets you specify a message that will display at compile time. The text of the message can be from a macro.

  • Macros can only be marked as deprecated with the deprecated pragma.

If the compiler encounters the use of a deprecated identifier, a C4996 warning is thrown.


The following sample shows how to mark functions as deprecated, and how to specify a message that will be displayed at compile time, when the deprecated function is used.

// deprecated.cpp
// compile with: /W3
#define MY_TEXT "function is deprecated"
void func1(void) {}
__declspec(deprecated) void func1(int) {}
__declspec(deprecated("** this is a deprecated function **")) void func2(int) {}
__declspec(deprecated(MY_TEXT)) void func3(int) {}

int main() {
   func1();
   func1(1);   // C4996
   func2(1);   // C4996
   func3(1);   // C4996
}

The following sample shows how to mark classes as deprecated, and how to specify a message that will be displayed at compile time, when the deprecated class is used.

// deprecate_class.cpp
// compile with: /W3
struct __declspec(deprecated) X {
   void f(){}
};

struct __declspec(deprecated("** X2 is deprecated **")) X2 {
   void f(){}
};

int main() {
   X x;   // C4996
   X2 x2;   // C4996
}



간단하게 말하자면 앞으로 사용하지 않을, 지원하지 않을, 삭제될 예정인 타입, 클래스, 함수 등을 컴파일 타임에 Warnning으로 처리되어 알리는 역할을 한다. 대충 보니 2003 부터 지원했던 것 같다. 그냥 그러하다.


#pragma deprecated

이런 것도 있는데 귀찮으니 다음에...




Windows 권한

저장소/VC++


출처 : 백발의 개발자님 블로그

Windows 권한 이해하기 1 : http://blog.naver.com/jjoommnn/130029014466

Windows 권한 이해하기 2 : http://blog.naver.com/jjoommnn/130029072191

Windows 권한 이해하기 3 : http://blog.naver.com/jjoommnn/130029485318

Windows 권한 이해하기 4 : http://blog.naver.com/jjoommnn/130029660867

Windows 권한 이해하기 예제 : http://blog.naver.com/jjoommnn/130041930878


게시물 없어지기 전에 내용 복사 예정, 헤헤

[C++] RTTI와 dynamic_cast

저장소/VC++

문제는 어쨋든 해결 했으나 정확한 원인을 파악하지 못했기에 남겨둔다.


RTTI는 Run-time Type Information 다. 그냥 그렇다구.

dynamic_cast를 사용하기 위해서는 /GR 옵션을 사용해야 한다. 맞나?

visual studio 6.0은 프로젝트 설정에서 따로 옵션을 추가하거나 사용을 체크해줘야 한다.

visual studio 2008은 기본 설정으로 되어있다. 더 자세한 내용은 그냥 검색하든가 책을 보자.


문제는 dynamic_cast를 사용하는 환경에는 아무 문제가 없는데 문제가 발생했다는거.

상속도 정상적이었고 생성도 문제 없었음.

업 캐스팅은 문제가 없었으나 다운 캐스팅을 할 때 NULL이 반환됨.

컴파일 과정에서 어떠한 경고나 에러 발생하지 않았음.

모든 상황을 다 확인했으나 문제 없어보였음.

결국 함수 단위로 쪼개서 테스트 해보니


error C2243: '형식 캐스팅' 발생!


원인은 상속받을 때 다음과 같이 했다는거.


class Book{};

class Bible : Book{};


이게 뭣이당가! public 빼먹었더니만 캐스팅 할 때 바로 문제가 나오는데!

왜 아무런 경고나 에러가 발생하지 않았었을까?

link 할 때 뭔가 잘못 된 것 같긴 한데 정확한 원인을 모르겠다!! @_@


'저장소 > VC++' 카테고리의 다른 글

deprecated 설정  (0) 2012.09.11
Windows 권한  (0) 2012.08.20
[Win32 API] 메모리 유효성 검증(사용 금지)  (0) 2012.06.20
Windows XP sp2 환경에서 exe 또는 dll 사용 시 재부팅 문제  (0) 2012.06.13
[MFC] CDockablePane  (0) 2012.02.10

[Win32 API] 메모리 유효성 검증(사용 금지)

저장소/VC++

참고 : http://blog.naver.com/winjks/10030145808


IsBadCodePtr : 현재의 프로세스가 해당 주소가 가리키는 영역을 읽을 수 있는지.
IsBadReadPtr : 현재의 프로세스가 해당 주속가 가리키는 영역을 읽을 수 있는지.
IsBadStringPtr : 현재의 프로세스가 해당 주속가 가리키는 영역을 문자열로 읽을 수 있는지의 여부 확인.
시작포인터로 부터 null이 나올때까지 유효성을 검사
IsBadWritePtr : 현재의 프로세스가 해당 주속가 가리키는 영역에 기록할 수 있는지.


하지만!!
MSDN을 보면 다음과 같은 내용이 있다.
나중에 언제 없어질지 몰라요~
그냥 쓰지 말자. ㅡㅜ

Important This function is obsolete and should not be used. Despite its name, it does not guarantee that the pointer is valid or that the memory pointed to is safe to use. For more information, see Remarks on this page.

Windows XP sp2 환경에서 exe 또는 dll 사용 시 재부팅 문제

저장소/VC++

Windows XP sp2 환경에서 exe 또는 dll 사용 시 재부팅 문제.

내가 찾은거 아니지만 정리..


MS 원문 : http://support.microsoft.com/kb/921337


Windows XP 서비스 팩 2(SP2)에서 Windows Vista 확장이 포함된 매니페스트를 .exe 또는 .dll 파일에 추가하면 컴퓨터가 다시 시작될 수 있다


Microsoft Windows Vista 확장이 포함된 매니페스트를 .exe 또는 .dll 파일에 추가하면 컴퓨터가 다시 시작될 수 있습니다. 이 문제는 Microsoft Windows XP 서비스 팩 2(SP2) 기반 컴퓨터에서 발생합니다. 또한 .exe 파일이 실행되거나 .dll 파일이 로드되는 경우에도 이 문제가 발생합니다. Microsoft Windows Vista 확장이 포함된 매니페스트 세그먼트의 예제는 다음과 같습니다.

//The section between >>>>> and <<<< is the problematic section. 

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
<assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="Synergex.Synergyde.lm" type="win32"> 
</assemblyIdentity> 
<dependency> 
<dependentAssembly> 
<assemblyIdentity 
   type="win32" name="Microsoft.VC80.CRT" version="8.0.50608.0" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"> 
</assemblyIdentity> 
</dependentAssembly> 
</dependency> 

>>>>>>>>>>> 

<ms_asmv3:trustInfo xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3" xmlns="urn:schemas-microsoft-com:asm.v3"> 
<ms_asmv3:security xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3"> 
<requestedPrivileges> 
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"> 
</requestedExecutionLevel> 
</requestedPrivileges> 
</ms_asmv3:security> 
</ms_asmv3:trustInfo> 

<<<<<<<<<<< 

</assembly> 

이 문제는 Csrss.exe에서 Windows Vista 확장이 포함된 매니페스트를 포함하는 .exe 파일이나 .dll 파일을 로드하는 경우 
발생합니다. Csrss.exe에서 포함된 매니페스트의 구문을 분석할 때 두 스키마 속성이 있는 단일 태그를 발견하면 내부 메모리가 손상될 수 
있습니다. 위의 예제에서 두 스키마 속성이 포함된 태그는 다음과 같습니다. 
<ms_asmv3:trustInfo xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3" xmlns="urn:schemas-microsoft-com:asm.v3">
Csrss.exe에서 이러한 태그를 발견하면 메모리 손상으로 인해 액세스 위반이 발생하며, 이 때문에 Windows가 다시 시작됩니다. 최종 사용자는 이 문서에서 설명하는 핫픽스를 구해 이 문제를 해결할 수 있습니다. 소프트웨어 개발자는 매니페스트의 모든 속성에 단일 스키마만 존재하도록 하여 이 문제를 방지할 수 있습니다. 위의 예제에서 다음과 같은 태그를 사용하면 이 문제가 방지됩니다.
<ms_asmv3:trustInfo xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
Visual Studio 2005에서 만든 매니페스트가 이 문제를 나타낼 수 있습니다. 이 문제는 Visual Studio 2005 서비스 팩 1에서 업데이트된 Mt.exe 파일로 해결됩니다.


[MFC] CDockablePane

저장소/VC++
출처 :  http://knob.egloos.com/2780159


1. CFrameWndEx 상속 클래스에 다음과 같이 CDockablePane 객체를 선언하고.

CDockablePane m_Panes[5]; // 필요한 만큼의 갯수로 선언

2. CFrameWndEx 상속 클래스의 OnCreate()에 다음과 같은 부분들이 있는지 확인 한 후에,

// 메뉴 모음을 활성화해도 포커스가 이동하지 않게 합니다.
CMFCPopupMenu::SetForceMenuFocus(FALSE);
// 사용자 정의 도구 모음 작업을 허용합니다.
InitUserToolbars(NULL, uiFirstUserToolBarId, uiLastUserToolBarId);
// 도구 모음 및 도킹 창 메뉴 바꾸기를 활성화합니다.
EnablePaneMenu(TRUE, ID_VIEW_CUSTOMIZE, 0, ID_VIEW_TOOLBAR);
// Visual Studio 2005 스타일 도킹 창 동작을 활성화합니다.
CDockingManager::SetDockingMode(DT_SMART);
// Visual Studio 2005 스타일 도킹 창 자동 숨김 동작을 활성화합니다.
EnableAutoHidePanes(CBRS_ALIGN_ANY);
// Enable Docking
EnableDocking(CBRS_ALIGN_ANY);

3. 그 뒤에 아래와 같이 배치해 준다.

if (!m_Panes[0].Create(_T("Pane 0"), this, CRect(0, 0, 200, 100), TRUE, 1000,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
m_Panes[0].EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_Panes[0]); // LEFT

if (!m_Panes[0].Create(_T("Pane 0"), this, CRect(0, 0, 200, 100), TRUE, 1000,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[1].Create(_T("Pane 1"), this, CRect(0, 0, 200, 100), TRUE, 1001,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_BOTTOM | CBRS_FLOAT_MULTI))
{return FALSE;}
m_Panes[0].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[1].EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_Panes[1]); // BOTTOM
DockPane(&m_Panes[0]); // LEFT


if (!m_Panes[0].Create(_T("Pane 0"), this, CRect(0, 0, 200, 100), TRUE, 1000,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[1].Create(_T("Pane 1"), this, CRect(0, 0, 200, 100), TRUE, 1001,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_BOTTOM | CBRS_FLOAT_MULTI))
{return FALSE;}
m_Panes[0].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[1].EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_Panes[0]); // LEFT
DockPane(&m_Panes[1]); // BOTTOM
if (!m_Panes[0].Create(_T("Pane 0"), this, CRect(0, 0, 200, 100), TRUE, 1000,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[1].Create(_T("Pane 1"), this, CRect(0, 0, 200, 100), TRUE, 1001,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
m_Panes[0].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[1].EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_Panes[0]); // LEFT
DockPane(&m_Panes[1]); // LEFT
// 0번을 2번의 위에 위치 시킨다.
m_Panes[0].DockToWindow(&m_Panes[1], CBRS_TOP);
if (!m_Panes[0].Create(_T("Pane 0"), this, CRect(0, 0, 200, 100), TRUE, 1000,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[1].Create(_T("Pane 1"), this, CRect(0, 0, 200, 100), TRUE, 1001,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
m_Panes[0].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[1].EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_Panes[0]); // LEFT
DockPane(&m_Panes[1]); // LEFT
CDockablePane* pTabbedBar = NULL;
// Tab 형식으로 붙인다. 
m_Panes[1].AttachToTabWnd(&m_Panes[0], DM_SHOW, TRUE, &pTabbedBar);


if (!m_Panes[0].Create(_T("Pane 0"), this, CRect(0, 0, 200, 100), TRUE, 1000,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[1].Create(_T("Pane 1"), this, CRect(0, 0, 200, 100), TRUE, 1001,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[2].Create(_T("Pane 2"), this, CRect(0, 0, 200, 100), TRUE, 1002,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
m_Panes[0].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[1].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[2].EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_Panes[0]); // LEFT
DockPane(&m_Panes[1]); // LEFT
DockPane(&m_Panes[2]); // LEFT
// 0번을 2번의 위에 위치 시킨다.
m_Panes[0].DockToWindow(&m_Panes[2], CBRS_TOP);
CDockablePane* pTabbedBar = NULL;
// 1을 0에 Tab 형식으로 붙인다. 
m_Panes[1].AttachToTabWnd(&m_Panes[0], DM_SHOW, TRUE, &pTabbedBar);
if (!m_Panes[0].Create(_T("Pane 0"), this, CRect(0, 0, 200, 100), TRUE, 1000,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_BOTTOM | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[1].Create(_T("Pane 1"), this, CRect(0, 0, 200, 100), TRUE, 1001,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_BOTTOM | CBRS_FLOAT_MULTI))
{return FALSE;}
m_Panes[0].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[1].EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_Panes[0]); // BOTTOM
DockPane(&m_Panes[1]); // BOTTOM
CDockablePane* pTabbedBar = NULL;
// 0번을 1번의 왼쪽에 위치 시킨다.
m_Panes[0].DockToWindow(&m_Panes[1], CBRS_LEFT);
if (!m_Panes[0].Create(_T("Pane 0"), this, CRect(0, 0, 200, 100), TRUE, 1000,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_BOTTOM | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[1].Create(_T("Pane 1"), this, CRect(0, 0, 200, 100), TRUE, 1001,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_BOTTOM | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[2].Create(_T("Pane 2"), this, CRect(0, 0, 200, 100), TRUE, 1002,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[3].Create(_T("Pane 3"), this, CRect(0, 0, 200, 100), TRUE, 1003,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[4].Create(_T("Pane 4"), this, CRect(0, 0, 200, 100), TRUE, 1004,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_RIGHT | CBRS_FLOAT_MULTI))
{return FALSE;}
m_Panes[0].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[1].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[2].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[3].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[4].EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_Panes[0]); // BOTTOM
DockPane(&m_Panes[1]); // BOTTOM
DockPane(&m_Panes[2]); // LEFT
DockPane(&m_Panes[3]); // LEFT
DockPane(&m_Panes[4]); // RIGHT
// 0번을 1번의 왼쪽에 위치 시킨다.
CDockablePane* pTabbedBar = NULL;
m_Panes[0].DockToWindow(&m_Panes[1], CBRS_LEFT);
// 3을 2에 Tab 형식으로 붙인다. 
m_Panes[3].AttachToTabWnd(&m_Panes[2], DM_SHOW, TRUE, &pTabbedBar);
if (!m_Panes[0].Create(_T("Pane 0"), this, CRect(0, 0, 200, 100), TRUE, 1000,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_BOTTOM | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[1].Create(_T("Pane 1"), this, CRect(0, 0, 200, 100), TRUE, 1001,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_BOTTOM | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[2].Create(_T("Pane 2"), this, CRect(0, 0, 200, 100), TRUE, 1002,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[3].Create(_T("Pane 3"), this, CRect(0, 0, 200, 100), TRUE, 1003,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
{return FALSE;}
if (!m_Panes[4].Create(_T("Pane 4"), this, CRect(0, 0, 200, 100), TRUE, 1004,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_RIGHT | CBRS_FLOAT_MULTI))
{return FALSE;}
m_Panes[0].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[1].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[2].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[3].EnableDocking(CBRS_ALIGN_ANY);
m_Panes[4].EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_Panes[0]); // BOTTOM
DockPane(&m_Panes[1]); // BOTTOM
DockPane(&m_Panes[2]); // LEFT
DockPane(&m_Panes[3]); // LEFT
DockPane(&m_Panes[4]); // RIGHT
CDockablePane* pTabbedBar = NULL;
// 1을 0에 Tab 형식으로 붙인다
m_Panes[1].AttachToTabWnd(&m_Panes[0], DM_SHOW, TRUE, &pTabbedBar);
// 3을 2에 Tab 형식으로 붙인다. 
m_Panes[3].AttachToTabWnd(&m_Panes[2], DM_SHOW, TRUE, &pTabbedBar); 

[MFC] Application Layout State - 레이아웃 상태(저장) 관련 내용

저장소/VC++
출처 :  http://surfree.egloos.com/10681365 


MS VS 2008부터 MFC Feature Pack을 지원합니다.

Doc-View 형태의 응용프로그램을 만들면 MFC Feature Pack에서 제공하는 OutlookBar 와 Docking Pane를 이용할 수 있습니다.

OutlookBar와 Docking Pane의 레이아웃은 자동으로 저장되고 로드 됩니다.

매우 편리한 기능이긴 하지만 또한 매우 불편한 기능입니다.

물론 이 레이아웃 상태에 대해서 커스터마이징을 할 수 있는 여지를 두었군요.

MFC Feature Pack으로 Doc-VIew 응용프로그램을 생성할 시 기본 App 클래스는

CWinApp에서 CWinAppEx로 변경됩니다.

CWinAppEx에서 이 상태 저장 및 복구를 하는 군요.

CWinAppEx의 메소드 중 다음 메소드를 주의해서 보시면 됩니다.

CleanState(): 레이아웃 상태를 모두 초기화 한다.
LoadState(): 레이아웃 상태를 로드한다.
SaveState(): 레이아웃 상태를 저장한다.

위와 같은 메소드가 있지만 CleanState() 정도가 유용하게 쓰일 수 있을 것 같습니다.

CWinAppEx를 상속받은 클래스의 InitInstance()에서

SetRegistryKey() 구문 다음에 CleanState()를 호출하면 항상 레이아웃이 초기화한 상태로 표시되게 됩니다.

레이아웃을 로드하는 시점은 ProcessShellCommand()에서 프레임워크상 자동으로 로딩되게 되어 있습니다.

또한 이 레이아웃 자동 저장이 필요없다면

CWinAppEx의 다음 메소드를 오버라이딩 합니다.

virtual void OnClosingMainFrame(CFrameImpl* pFrameImpl);

기본 동작은 SaveState() 메소드를 호출합니다.

그러므로 레이아웃 자동저장이 되지 않게 하기 위해서는 OnClosingMainFrame()메소드를 오버라이딩하여 빈 구문으로 놓으면 레이아웃이 자동으로 저장되지 않습니다.  

[Debugging] First-chance Exception과 Second-chance Exception

저장소/VC++
출처 : http://blog.naver.com/saojung50/120038406993


First-chance Exception...




처음 프로그램을 실행하면..

쓰레드를 생성하게 됍니다.

그 부분에서

First-chance exception이 나오는데요...

디버그 랩에서 보고 브레이크 포인터 까지 거는것 까지 했습니다.

하지마나 어디서 그 부분이 나오는지를 찾지 못하겠더군요..

쓰레드 생성 부분을 제거 하고 프로젝트를 실행하면 나오지는 않는데요..

왜 이런 현상이 나오는지 모르겠습니다.

여러 쓰레드를 생성하지만 특별히 몇개의 쓰레드에서만 나오는거 같은데요..

 

특별한 원인이 없는거 같은데..잘 모르겠더군요..

 

해결의 실마리가 있을런지 해서 이렇게 조언을 구합니다.

조언 부탁드리겠습니다.






답글 작성자 : 서우석 등록일 : 2004-06-01 오후 10:34

Re : First-chance Exception...




안녕하세요. 좋은 질문이네요..

우선 First-Chance Exception에 대해서 Microsoft의 KB에서 다음과 같이 소개하고 있습니다.

http://support.microsoft.com/default.aspx?kbid=105675

It is a common practice to use SEH as a signaling mechanism. Some application programming interfaces (APIs) register an exception handler in anticipation of a failure condition that is expected to occur in a lower layer.

When an exception is raised, the handler may correct or ignore the condition rather than allow a failure to propagate up through intervening layers. This is very useful in complex environments such as networks where partial failures are expected and it is not desirable to fail an entire operation just because one of several optional parts failed. In this case, the exception can be handled so that the application does not recognize that an exception has occurred.

However, if the application is being debugged, the debugger sees all exceptions before the program does. This is the distinction between the first and second chance exception: the debugger gets the first chance to see the exception (hence the name). If the debugger allows the program execution to continue and does not handle the exception, the program will see the exception as usual. If the program does not handle the exception, the debugger gets a second chance to see the exception. In this latter case, the program normally would crash if the debugger were not present.

해석 : 하지만 만약 응용 프로그램이 디버깅되고 있는 중이라면, 디버거는 프로그램이 예외를 확인하기 전에 먼저 모든 예외를 감시한다. 이것이 바로 첫번째(first-chance)와 두번째(second-chance) 예외의 차이점이다. 디버거는 프로그램에서 발생하는 모든 예외를 살펴볼 수 있는 가장 첫번째 기회(first-chance라고 하는 이유)를 갖게된다. 만약 디버거가 프로그램 실행을 계속 허용하고 해당 예외를 처리하지 않는다면, 프로그램은 평상시와 마찬가지로 예외를 확인하게 될 것이다. 만약 프로그램이 그 예외를 처리하지 않는다면, 디버거는 프로그램이 처리하지 않은 예외를 최종적으로 다시 한번 확인할 수 있는 두번째 기회(second-chance)를 갖게된다. 후자의 경우에는 일반적으로 디버거가 존재하지 않을 경우에 프로그램이 곧바로 충돌할 것이다.

* 보충 설명 ---------------

일반적으로 first-chance exception이 발생했다는 메시지를 확인했음에도 불구하고 프로그램이 충돌하지 않는 이유는 내부 코드에서 이 예외를 처리하고 있기 때문이라고 보시면 됩니다. 따라서 API를 호출하는 대부분의 경우에는 first-chance exception이 발생했다고 하더라도 무시하면 됩니다(내부적으로 처리가 되고 있기 때문이죠). 물론, first-chance exception을 확인하고 난 후, second-chance exception이 발생하여 프로그램이 충돌하면 당연히 오류를 잡아주어야 겠죠.

If you do not want to see the first chance exception in the debugger, you should disable first chance exception handling for the specific exception code. Otherwise, when the first chance exception occurs, you may need to instruct the debugger to pass on the exception to the program to be handled as usual.

 

만약 Visual Studio 6.0을 사용하고 계시다면, 이 툴로 first-chance exception을 잡을 방법이 없습니다. 다음 링크에서 WinDBG를 다운로드 하시면 간단하게 잡을 수 있죠. VS.NET에서는 원하는 exception을 선택할 수 있기 때문에 더욱 간단하구요. 물론 BoundsChecker와 같은 프로그램을 사용하셔도 잡으실 수 있을 것입니다. 결국 이 메세지를 디버깅 시에 확인하더라도 API 단에서 발생하는 경우라면 크게 걱정하지 않아도 건강에는 지장이 없다라는 것입니다. ^^

http://www.microsoft.com/ddk/debugging/

 




답글 작성자 : 박시존 등록일 : 2004-06-11 오후 3:54

Re : First-chance Exception...




 이런 경우에는 Debug -> exception -> 다이알로그 창에서 맨 밑의 항목 Microsoft C++ Exception을 stop always로 설정하셔도 많은 부분을 잡아낼 수 있습니다. 이렇게 해두면 예를 들어 DB exception이 발생하여 보통때는 "~ 테이블을 찾을 수 없습니다.." 정도로 메시지를 뿌려주고 지나가는 경우에도 먼저 브레이크가 걸린 다음에 메시지 박스가 나타나는 것에서부터 쓰레드 관련 오류 메모리 관련 오류( Access Violation을 stop always로 설정)등등 많은 부분이 미리 캐치됩니다. visual studio 6.0에서 사용하는 내용이고 Debug -> exception 메뉴는 프로그램 실행 중에만 활성화됩니다. F5 누르고 프로그램 시작하셔서 설정하시면 됩니다.




답글 작성자 : 관리자 등록일 : 2004-06-11 오후 11:15

Re : First-chance Exception...




좋은 답변 감사합니다. ^^

 

출처 : http://www.debuglab.com/board/board_detail.aspx?id=128&table=qna&pagenum=10


====================================================================================
내용 추가:
debug 모드에서 try-catch를 사용하여 exception 발생 상황을 확인하는 것이 아닌 exception이 발생하는 위치를 확인하고자 할 경우 메뉴의 'Debug-Exceptions'에서 'C++ Exceptions'와 'Win32 Exceptions'를 check하면 exception 발생 시 해당 위치를 확인할 수 있다.


'저장소 > VC++' 카테고리의 다른 글

[MFC] CDockablePane  (0) 2012.02.10
[MFC] Application Layout State - 레이아웃 상태(저장) 관련 내용  (0) 2012.02.10
[Win32 API] GetAsyncKeyState  (0) 2011.11.25
[MFC] DestroyWindow  (0) 2011.11.24
[MFC] MainFrame 크기 고정  (0) 2011.10.21

[Win32 API] GetAsyncKeyState

저장소/VC++
참고 : http://debugjung.tistory.com/trackback/364
MSDN : http://msdn.microsoft.com/ko-kr/site/ms646293

마우스의 버튼을 동시에 눌렀을 때 상태를 확인하는 방법.
마우스가 아닌 다른 키도 가능.

일단 테스트를 위해 WM_LBUTTONDOWN, WM_RBOUTTONDOWN 메시지를 확인한다.

void CTestDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: Add your message handler code here and/or call default

    SHORT nAsyncKey = GetAsyncKeyState(VK_RBUTTON);
    CString sTemp = _T("");
    sTemp.Format(_T("OnLButtonDown - Flags: 0x%08X / AsyncKey: 0x%04X\n"), nFlags, nAsyncKey);

    ::OutputDebugString(sTemp);

    CDialog::OnLButtonDown(nFlags, point);
}

void CTestDlg::OnRButtonDown(UINT nFlags, CPoint point)
{
    // TODO: Add your message handler code here and/or call default

    SHORT nAsyncKey = GetAsyncKeyState(VK_LBUTTON);
    CString sTemp = _T("");
    sTemp.Format(_T("OnRButtonDown - Flags: 0x%08X / AsyncKey: 0x%04X\n"), nFlags, nAsyncKey);

    ::OutputDebugString(sTemp);

    CDialog::OnRButtonDown(nFlags, point);
}

GetAsyncKeyState의 Return Value는 SHORT으로 의미하는 내용은 다음과 같다.
(debugjung 님이 정리해주신 내용 퍼옴)

0x0000: 이전에 누른 적이 없고 호출시점에 안 눌린 상태
0x8000: 이전에 누른 적이 없고 호출시점에 눌린 상태
0x8001: 이전에 누른 적이 있고 호출시점에 눌린 상태
0x0001: 이전에 누른 적이 있고 호출시점에 안 눌린 상태

매크로를 이용한 응용 방법은 다음과 같다.

#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEY_UP(vk_code)       ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)

간단하게 마우스 이벤트로 테스트 해보면 금방 이해가 된다. 끝.