zxphxh 2023-01-10 08:02 采纳率: 40%
浏览 14
已结题

继承CObject的lib,用dll调用产生异常


// (1) 创建一个lib项目:Tlib.lib
// 定义一个类CT,继承CObject
class CT : public CObject
{
private:
int a;
public:
void set(int na) { a = na; }
int get() { return a; }
CT() { a = 0; }
~CT() {}
};

// (2)定义一个类CTA, CT类为CTA的一个属性
#include "T.h"
class CTA
{
private:
CT *m_pT;
public:
CT* CreateNewT();
void SetT(CT* pT);

CTA();
 ~CTA();
};

CTA::CTA()
{
m_pT = NULL;
}
CTA::~CTA()
{
if (m_pT)
{
delete m_pT; m_pT = NULL;
}
}
CT* CTA::CreateNewT()
{
m_pT = new CT(); 
return m_pT;
} 

// (3) 创建一个dll调用CTA类
// 在stdafx.h中加入:
#pragma comment(lib, "Tlib.lib")

#define TLIB_EXPORT
#ifdef  TLIB_EXPORT
#define TLIB_API extern "C" __declspec(dllexport)
#else
#define TLIB_API extern "C" __declspec(dllimport)
#endif


TLIB_API int DoAlib(CTA *pTA)
{
if (pTA)
{
  pTA->CreateNewT();
}
return 0;
}

// (4)创建一个MFC对话框程序,m_pTA在头文件中定义,并在对话框构造函数中初始化:m_pTA = new CTA();
// 对话框上放置一个Button按钮,按钮事件:
void CCexeDlg::OnBnClickedButton1()
{
typedef void(*DoTA) (CTA *);
HMODULE hLibrary = LoadLibrary(L"bdll.dll");             
if (hLibrary)                                     
{
DoTA lpFunc = (DoTA)GetProcAddress(hLibrary, "DoAlib");  
if (lpFunc) (*lpFunc)(m_pTA);
FreeLibrary(hLibrary);                                 
}
}
//重载对话框DestroyWindow()
{
    if (m_pTA)
    {
        delete m_pTA; m_pTA = NULL;
    }
}

// (5) 点击Button按钮,无异常,但关闭对话框会显示异常:
// 0x00007FF72CE92E0A 处有未经处理的异常(在 Cexe.exe 中): 0xC0000005: 读取位置 0x00007FFF42FE3360 时发生访问冲突。
// 异常定位在delete m_pTA; m_pTA = NULL;语句。
// 如果把class CT : public CObject修改为class CT,不再继承CObject类,则不会产生异常。
// 请问是何种原因?如何解决?

  • 写回答

1条回答 默认 最新

  • m0_54204465 2023-01-10 08:48
    关注

    当CObject的派生类中使用delete时,如果对象正在被跟踪,则将调用CObject::InternalRelease。如果对象是通过new分配的,则该对象的内存被释放,并且内存跟踪信息被删除。如果对象是从非MFC内存分配函数分配的,则只会删除内存跟踪信息。

    在你的代码中,CTA的析构函数中调用了delete m_pT,但是m_pT是通过new分配的内存,在释放内存前会调用CObject的InternalRelease函数。如果在DLL中的CT对象已被加载并在调用DLL中的函数时被锁定,则InternalRelease函数将导致访问冲突。

    为了解决此问题,可以使用下列方法之一:
    在DLL中重载CObject::InternalRelease函数,并确保在调用之前解锁对象。

    使用动态分配的内存(使用malloc和free)来实例化CT对象,从而避免调用InternalRelease。

    不使用CObject的派生类,而是使用基本的C++类。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 1月21日
  • 已采纳回答 1月13日
  • 创建了问题 1月10日

悬赏问题

  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥170 如图所示配置eNSP
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改
  • ¥20 wireshark抓不到vlan
  • ¥20 关于#stm32#的问题:需要指导自动酸碱滴定仪的原理图程序代码及仿真
  • ¥20 设计一款异域新娘的视频相亲软件需要哪些技术支持
  • ¥15 stata安慰剂检验作图但是真实值不出现在图上
  • ¥15 c程序不知道为什么得不到结果