2019/03/06

[MFC] Document/View Architecture를 사용하지 않고 FormView 사용하기

CFormView를 이용한 간단한 프로그램을 만들 때 Visual C++ 에서 제공하는 Document/View Architecture를 사용할 경우 불필요한 작업이 많은 것 같아 이를 사용하지 않고 만드는 방법을 알아보았다. 

SDI 프로젝트를 만들때 Document/View Architecture 옵션을 제거하고 프로젝트를 만든 후 기본적으로 만들어지는 View외에 추가로 CFormView를 상속받는 View을 하나 만들어 기존 View와 교체를 하면 가능하였다.

하지만 새로운 View를 만들어 교체를 할 때 일반 변수를 이용하여 Stack에 만들경우 프로그램 종료시 에러가 발생하였다. 이미 해제된 View를 다시한 번 삭제하려 하기때문인 것 같았다. Heap 메모리에 만들어지도록 하면 문제가 없었다.

//CChildFormView.h
class CChildFormView : public CFormView
{
public:  // Change constructor to public. It is private by default
 CChildFormView();           // protected constructor used by dynamic creation
 virtual ~CChildFormView();
};




//CMainFrm.h
#include "ChildFormView.h"

class CMainFrame : public CFrameWnd
{
protected:  // control bar embedded members
 CChildFormView    *m_pWndView;
};




//CMainFrm.cpp
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
 if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
  return -1;

 // First, build the view context structure
 CCreateContext ccx;

 // Designate the class from which to build the view
 ccx.m_pNewViewClass = RUNTIME_CLASS(CChildFormView);

 // Using the structure, create a view
 m_pWndView = DYNAMIC_DOWNCAST(CChildFormView, this->CreateView(&ccx));

 // Did we succeed ?
 if (!m_pWndView)
 {
  TRACE0("Creation of view failed\n");
  return -1;
 }

 // Do layout recalc
 RecalcLayout();

 // Show the view and do an initial update
 m_pWndView->ShowWindow(SW_SHOW);
 m_pWndView->OnInitialUpdate();

 // Set this view active
 SetActiveView(m_pWndView);

 // Order it to resize the parent window to fit
 m_pWndView->ResizeParentToFit(FALSE);

 // create a view to occupy the client area of the frame
//  if (!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL))
//  {
//   TRACE0("Failed to create view window\n");
//   return -1;
//  }

 if (!m_wndStatusBar.Create(this))
 {
  TRACE0("Failed to create status bar\n");
  return -1;      // fail to create
 }
 m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT));

 return 0;
}


https://www.codeproject.com/Articles/5445/Using-views-effectively-without-the-doc-view-overh

Visual C++ 디버깅 메모리 상태

0xcccccccc (3435973836)
할당된 Stack 메모리를 초기화 하지 않을 경우 채워지는 값
해당 값은 어셈블리 __asm int 3(break)와 동일하여 이 영역을 접근하면 break point에 적중된다.
When the code is compiled with the /GZ option, uninitialized variables are automatically assigned to this value (at byte level).

0xcdcdcdcd (3452816845)
할당된 Heap 메모리를 초기화 하지 않을 경우 채워지는 값
Clean Memory: Allocated memory via malloc or new but never written by the application.

0xdddddddd (3722304989)
0xfeeefeee (4277075694)
Free 된 Heap 메모리에 채워지는 값
Dead Memory: Memory that has been released with delete or free. It is used to detect writing through dangling pointers.

0xfdfdfdfd (4261281277)
할당된 Heap 메모리의 경계(전,후)에 채워지는 값
Fence Memory: Also known as "no mans land." This is used to wrap the allocated memory (like surrounding it with fences) and is used to detect indexing arrays out of bounds.

0xABABABAB (‭2880154539‬)
HeapAlloc으로 메모리 할당 후 가드 바이트에 채워진 값
(Allocated Block?): Memory allocated by LocalAlloc().

0xBAADF00D (‭3131961357‬)
LocalAlloc(LMEM_FIXED)으로 메모리를 할당한 후 초기화하지 않음
Bad Food: Memory allocated by LocalAlloc() with LMEM_FIXED, but not yet written to.

https://www.codeguru.com/cpp/w-p/win32/tutorials/article.php/c9535/Inside-CRT-Debug-Heap-Management.htm