【发布时间】:2018-01-16 16:39:43
【问题描述】:
使用/clr VS2010 编写的MFC 应用程序。多线程 DLL (/MD) 运行时库。当我将NDEBUG 的预处理器定义切换到_DEBUG 时出现问题。 NDEBUG 禁用在定义 _DEBUG 时弹出的断言。我在管理类指针的创建和删除方面做错了吗?
从 NDEBUG 切换到 _DEBUG 后,我在运行时收到“_Block_Type_Is_Valid (pHead->nBlockUse)”断言失败错误。
A 类:“A.h”
#include "B.h"
class A
{
public:
A(void);
~A(void);
A(const A&);
A& operator=(const A&);
B* p_B;
};
A 类:“A.cpp”
#include "StdAfx.h"
#include "A.h"
A::A(void)
{
p_B = new B();
}
A::~A(void)
{
delete p_B;
}
// 1. copy constructor
A::A(const A& that)
{
p_B = new B();
*p_B = *that.p_B;
}
// 2. copy assignment operator
A& A::operator=(const A& that)
{
*p_B = *that.p_B;
return *this;
}
B 类:“B.h”
class B
{
public:
B(void);
~B(void);
B(const B&);
B& operator=(const B&);
};
B 类:“B.cpp”
#include "StdAfx.h"
#include "B.h"
B::B(void) { }
B::~B(void) { }
// 1. copy constructor
B::B(const B& that)
{
}
// 2. copy assignment operator
B& B::operator=(const B& that)
{
return *this;
}
ModalDlg.cpp(实例化A类对象的地方)
BOOL CTestingReleaseBuildDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
A a;
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
然后我只是在我的 MFC 对话框中实例化 A 类,这会导致断言失败。我的问题是,“我在创建和删除类指针时做错了吗?”断言在类 A 的析构函数的“删除 p_B”指令中特别失败。
编辑:
我用BOOL CMyMFCClassDLG::OnInitDialog() { ... A a; ...}实例化A类
编辑2: 我为 A 类和 B 类定义了复制构造函数和复制赋值运算符。它们永远不会被调用。
EDIT3:值得一提的是,如果我删除 A 的析构函数中的 delete p_B; 语句,则不会再出现断言失败。
EDIT4:在定义了 /MDd 和 _DEBUG 的调试模式下,程序运行良好。当我使用 /MD 和 _DEBUG 在发布模式下运行时,断言失败。我认为这可能会导致问题,因为 /MD 可能应该与 NDEBUG 一起运行。
EDIT5:我按照@Christophe 的建议更新了代码,并插入了实例化A 类对象的函数。我不想复制/粘贴模态对话框应用程序的其余部分,但您可以通过在 VS2010 中启动一个新的基于模态对话框的 MFC 应用程序来复制确切的代码,并将项目配置更改为使用 /CLR 模式,设置运行时库到 /MD 并在预处理器定义字段中包含 _DEBUG 关键字。
EDIT6:链接到项目https://drive.google.com/drive/folders/1q0n9c6yMZ2ZKnakH6Z5NbVeGsAWfUAc1?usp=sharing
【问题讨论】:
-
你违反了 3/5/0 的规则。
-
你如何实例化它?如果你使用
operator = (...),你就有麻烦了。 -
当
B可以工作时,为什么还要使用B *? -
断言失败的最可能原因是您多次删除同一个对象。这可能是由复制
a引起的,例如,如果您使用A a = A();实例化它或将a按值传递给函数或...