问题描述
我使用MFC AppWizard创建了一个SDI应用‘test’,未勾选ActiveX控件,其它为默认设置。然后为CTestView类添加成员变量CString m_strName,创建对话框类CTestDialog,并使用向导为其添加成员变量CTime m_dataTime(自动添加DDX函数)。
之后,在CTestView::OnDraw(CDC* pDC)中创建CTestDialog对象dlg,使用DoModal生成窗口后,对m_strName重新赋值。编译通过,但运行出错。
在Debug的时候发现,调用了DoModal之后,原本保存m_strName地址的那部分内存(4字节)内容会被修改,导致找不到m_strName的值(新地址越界了,原地址指向的内容没变)。
而在我单独使用EditBox控件的时候则不会出现这样的问题,所以我想知道这中间发生了什么,有什么区别以及该如何正确使用DataTimePicker控件。代码部分
testView.h// testView.h : interface of the CTestView class
//
/////////////////////////////////////////////////////////////////////////////#if !defined(AFX_TESTVIEW_H__85D7C03F_39A6_4535_80A5_5E109333D12B__INCLUDED_)
#define AFX_TESTVIEW_H__85D7C03F_39A6_4535_80A5_5E109333D12B__INCLUDED_#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CTestView : public CView
{
protected: // create from serialization only
CTestView();
DECLARE_DYNCREATE(CTestView)// Attributes
public:
CTestDoc* GetDocument();
CString m_strName;// Operations
public:// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CTestView)
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
//}}AFX_VIRTUAL// Implementation
public:
virtual ~CTestView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endifprotected:// Generated message map functions
protected:
//{{AFX_MSG(CTestView)
// NOTE - the ClassWizard will add and remove member functions here.
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};#ifndef _DEBUG // debug version in testView.cpp
inline CTestDoc* CTestView::GetDocument()
{ return (CTestDoc*)m_pDocument; }
#endif///////////////////////////////////////////////////////////////////////////////{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_TESTVIEW_H__85D7C03F_39A6_4535_80A5_5E109333D12B__INCLUDED_)
testView.cpp// testView.cpp : implementation of the CTestView class
//#include "stdafx.h"
#include "test.h"#include "testDoc.h"
#include "testView.h"#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif/////////////////////////////////////////////////////////////////////////////
// CTestViewIMPLEMENT_DYNCREATE(CTestView, CView)BEGIN_MESSAGE_MAP(CTestView, CView)
//{{AFX_MSG_MAP(CTestView)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
// CTestView construction/destructionCTestView::CTestView()
{
// TODO: add construction code here
m_strName="0000";
}CTestView::~CTestView()
{
}BOOL CTestView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs return CView::PreCreateWindow(cs);
}/////////////////////////////////////////////////////////////////////////////
// CTestView drawingvoid CTestView::OnDraw(CDC* pDC)
{
CTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
CTestDialog dlg;
dlg.DoModal();
m_strName="11111";
}/////////////////////////////////////////////////////////////////////////////
// CTestView printingBOOL CTestView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}void CTestView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}void CTestView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}/////////////////////////////////////////////////////////////////////////////
// CTestView diagnostics#ifdef _DEBUG
void CTestView::AssertValid() const
{
CView::AssertValid();
}void CTestView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}CTestDoc* CTestView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTestDoc)));
return (CTestDoc*)m_pDocument;
}
#endif //_DEBUG/////////////////////////////////////////////////////////////////////////////
// CTestView message handlersDialogs.h#if !defined(AFX_DIALOGS_H__32ACF32B_B56E_4CFB_A5AE_E6F2F343DF92__INCLUDED_)
#define AFX_DIALOGS_H__32ACF32B_B56E_4CFB_A5AE_E6F2F343DF92__INCLUDED_#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// Dialogs.h : header file
///////////////////////////////////////////////////////////////////////////////
// CTestDialog dialogclass CTestDialog : public CDialog
{
// Construction
public:
CTestDialog(CWnd* pParent = NULL); // standard constructor// Dialog Data
//{{AFX_DATA(CTestDialog)
enum { IDD = IDD_DIALOG1 };
CTime m_dateTime;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CTestDialog)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL// Implementation
protected: // Generated message map functions
//{{AFX_MSG(CTestDialog)
// NOTE: the ClassWizard will add member functions here
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_DIALOGS_H__32ACF32B_B56E_4CFB_A5AE_E6F2F343DF92__INCLUDED_)Dialogs.cpp// Dialogs.cpp : implementation file
//#include "stdafx.h"
#include "test.h"
#include "Dialogs.h"#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif/////////////////////////////////////////////////////////////////////////////
// CTestDialog dialog
CTestDialog::CTestDialog(CWnd* pParent /*=NULL*/)
: CDialog(CTestDialog::IDD, pParent)
{
//{{AFX_DATA_INIT(CTestDialog)
m_dateTime = 0;
//}}AFX_DATA_INIT
}
void CTestDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CTestDialog)
DDX_DateTimeCtrl(pDX, IDC_DATETIMEPICKER1, m_dateTime);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CTestDialog, CDialog)
//{{AFX_MSG_MAP(CTestDialog)
// NOTE: the ClassWizard will add message map macros here
//}}AFX_MSG_MAP
END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
// CTestDialog message handlers
我使用MFC AppWizard创建了一个SDI应用‘test’,未勾选ActiveX控件,其它为默认设置。然后为CTestView类添加成员变量CString m_strName,创建对话框类CTestDialog,并使用向导为其添加成员变量CTime m_dataTime(自动添加DDX函数)。
之后,在CTestView::OnDraw(CDC* pDC)中创建CTestDialog对象dlg,使用DoModal生成窗口后,对m_strName重新赋值。编译通过,但运行出错。
在Debug的时候发现,调用了DoModal之后,原本保存m_strName地址的那部分内存(4字节)内容会被修改,导致找不到m_strName的值(新地址越界了,原地址指向的内容没变)。
而在我单独使用EditBox控件的时候则不会出现这样的问题,所以我想知道这中间发生了什么,有什么区别以及该如何正确使用DataTimePicker控件。代码部分
testView.h// testView.h : interface of the CTestView class
//
/////////////////////////////////////////////////////////////////////////////#if !defined(AFX_TESTVIEW_H__85D7C03F_39A6_4535_80A5_5E109333D12B__INCLUDED_)
#define AFX_TESTVIEW_H__85D7C03F_39A6_4535_80A5_5E109333D12B__INCLUDED_#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CTestView : public CView
{
protected: // create from serialization only
CTestView();
DECLARE_DYNCREATE(CTestView)// Attributes
public:
CTestDoc* GetDocument();
CString m_strName;// Operations
public:// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CTestView)
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
//}}AFX_VIRTUAL// Implementation
public:
virtual ~CTestView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endifprotected:// Generated message map functions
protected:
//{{AFX_MSG(CTestView)
// NOTE - the ClassWizard will add and remove member functions here.
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};#ifndef _DEBUG // debug version in testView.cpp
inline CTestDoc* CTestView::GetDocument()
{ return (CTestDoc*)m_pDocument; }
#endif///////////////////////////////////////////////////////////////////////////////{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_TESTVIEW_H__85D7C03F_39A6_4535_80A5_5E109333D12B__INCLUDED_)
testView.cpp// testView.cpp : implementation of the CTestView class
//#include "stdafx.h"
#include "test.h"#include "testDoc.h"
#include "testView.h"#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif/////////////////////////////////////////////////////////////////////////////
// CTestViewIMPLEMENT_DYNCREATE(CTestView, CView)BEGIN_MESSAGE_MAP(CTestView, CView)
//{{AFX_MSG_MAP(CTestView)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
// CTestView construction/destructionCTestView::CTestView()
{
// TODO: add construction code here
m_strName="0000";
}CTestView::~CTestView()
{
}BOOL CTestView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs return CView::PreCreateWindow(cs);
}/////////////////////////////////////////////////////////////////////////////
// CTestView drawingvoid CTestView::OnDraw(CDC* pDC)
{
CTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
CTestDialog dlg;
dlg.DoModal();
m_strName="11111";
}/////////////////////////////////////////////////////////////////////////////
// CTestView printingBOOL CTestView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}void CTestView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}void CTestView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}/////////////////////////////////////////////////////////////////////////////
// CTestView diagnostics#ifdef _DEBUG
void CTestView::AssertValid() const
{
CView::AssertValid();
}void CTestView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}CTestDoc* CTestView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTestDoc)));
return (CTestDoc*)m_pDocument;
}
#endif //_DEBUG/////////////////////////////////////////////////////////////////////////////
// CTestView message handlersDialogs.h#if !defined(AFX_DIALOGS_H__32ACF32B_B56E_4CFB_A5AE_E6F2F343DF92__INCLUDED_)
#define AFX_DIALOGS_H__32ACF32B_B56E_4CFB_A5AE_E6F2F343DF92__INCLUDED_#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// Dialogs.h : header file
///////////////////////////////////////////////////////////////////////////////
// CTestDialog dialogclass CTestDialog : public CDialog
{
// Construction
public:
CTestDialog(CWnd* pParent = NULL); // standard constructor// Dialog Data
//{{AFX_DATA(CTestDialog)
enum { IDD = IDD_DIALOG1 };
CTime m_dateTime;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CTestDialog)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL// Implementation
protected: // Generated message map functions
//{{AFX_MSG(CTestDialog)
// NOTE: the ClassWizard will add member functions here
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_DIALOGS_H__32ACF32B_B56E_4CFB_A5AE_E6F2F343DF92__INCLUDED_)Dialogs.cpp// Dialogs.cpp : implementation file
//#include "stdafx.h"
#include "test.h"
#include "Dialogs.h"#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif/////////////////////////////////////////////////////////////////////////////
// CTestDialog dialog
CTestDialog::CTestDialog(CWnd* pParent /*=NULL*/)
: CDialog(CTestDialog::IDD, pParent)
{
//{{AFX_DATA_INIT(CTestDialog)
m_dateTime = 0;
//}}AFX_DATA_INIT
}
void CTestDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CTestDialog)
DDX_DateTimeCtrl(pDX, IDC_DATETIMEPICKER1, m_dateTime);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CTestDialog, CDialog)
//{{AFX_MSG_MAP(CTestDialog)
// NOTE: the ClassWizard will add message map macros here
//}}AFX_MSG_MAP
END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
// CTestDialog message handlers
仅供参考:#include <time.h>
#include <stdlib.h>
#include <windows.h>
int main() {
int a,b[11];//本来是b[10],为判断哪句越界,故意声明为b[11] srand((unsigned int)time(NULL));//按两次F11,等黄色右箭头指向本行时,调试、新建断点、新建数据断点,地址:&b[10],字节计数:4,确定。
while (1) {//按F5,会停在下面某句,此时a的值为10,b[10]已经被修改为对应0..4之一。
b[(a=rand()%11)]=0;
Sleep(100);
b[(a=rand()%11)]=1;
Sleep(100);
b[(a=rand()%11)]=2;
Sleep(100);
b[(a=rand()%11)]=3;
Sleep(100);
b[(a=rand()%11)]=4;
Sleep(100);
}
return 0;
}