MFC dll 中的访问冲突(用 C++/CLI 包装)从 C# 程序开始
Posted
技术标签:
【中文标题】MFC dll 中的访问冲突(用 C++/CLI 包装)从 C# 程序开始【英文标题】:Access violation in MFC dll (wrapped in C++/CLI) started from C# program 【发布时间】:2011-07-14 13:32:54 【问题描述】:我为 mfc dll (C++) 编写了一个托管 C++/CLI 包装器,并且在第二次调用 dll 后出现了一些访问冲突!
包装器
// in .h
typedef CKeyManagerServerApp* (*KeyManagerInstance)(CCommonUtils *);
ManagedKeyInterface::ManagedKeyInterface()
HINSTANCE m_keyManagerLib = LoadLibrary("pathToDll");
KeyManagerInstance _createInstance = (KeyManagerInstance)GetProcAddress(m_keyManagerLib, "GetInstance");
// get native reader interface from managed reader interface
CCommonUtils *nativeReaderInterface = static_cast<CCommonUtils*>(readerInterface->nativeReaderInterface.ToPointer());
CKeyManagerServerApp *m_keyManagerApp = (_createInstance)(nativeReaderInterface );
ManagedKeyInterface::~ManagedKeyInterface()
try
DestroyKeyManagerInstance _destroyInstance = (DestroyKeyManagerInstance)GetProcAddress(m_keyManagerLib, "DestroyInstance");
(_destroyInstance)(m_keyManagerApp);
FreeLibrary(m_keyManagerLib);
catch(System::Exception ^e)
FreeLibrary(m_keyManagerLib);
本地 MFC 类
extern "C" _declspec(dllexport) CKeyManagerServerApp* GetInstance(CCommonUtils *readerInterface)
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return new CKeyManagerServerApp(readerInterface);
extern "C" _declspec(dllexport) void DestroyInstance(CKeyManagerServerApp *ptr)
AFX_MANAGE_STATE(AfxGetStaticModuleState());
delete ptr;
// constructor
CKeyManagerServerApp::CKeyManagerServerApp(CCommonUtils *readerInterface)
m_log = new Logging(loggingFilePath); // <--- ERROR at second call
// reader interface object for communication
m_readerComm = new ReaderCommunication(readerInterface, m_log);
m_smartmaskcmds = new CSmartMaskCmds(m_readerComm, m_log);
readerInterface = NULL;
// destructor
CKeyManagerServerApp::~CKeyManagerServerApp()
// destruct objects
delete m_smartmaskcmds;
delete m_readerComm;
delete m_log;
在 ReaderCommunication 和 CSmartMaskCmds 中。该对象只会被分配!
在 C# 程序的第一次运行时(加载带有添加引用的包装器)一切正常,但是当我再次启动它时,我得到:
TestKeyManagerApp.exe 中 0x76f85b57 处的第一次机会异常:0xC0000005:访问冲突读取位置 0xdddddddd。 TestKeyManagerApp.exe 中 0x75169617 处的第一次机会异常:Microsoft C++ 异常:内存位置 0x0024e820 处的 CMemoryException..
当我调用 m_log = new Logging(loggingFilePath)
看来析构函数不能正常工作!?
有什么想法!!??
谢谢!
【问题讨论】:
MFC 有一些关于管理全局状态和 DllMain() 的非常难以理解的规则。在我看来,第二次加载 DLL 时没有发生一些初始化。很难理解为什么要这样做,只需链接到 DLL 的导入库,这样您就可以直接调用方法并完成它。 谢谢!但是当 dll 发生变化时,不应该每次都重新编译包装器!提示:我还在 destr 中收到错误消息。第一次运行时的 CKeyManagerServerApp (目标不干净??? -> 所以一些内存伪影或分配仍然存在) 崩溃的调用栈是什么? 嗨!我发现从 CWinApp 派生我的基本 MFC 类并为每个导出的方法使用 AFX_MANAGE_STATE(AfxGetStaticModuleState()) 是必不可少的!我还使用指向另一个对象的指针作为constr。参数(当我理解正确时,这在常规 mfc dll 中是不可能的-> 但我也不能使用扩展 dll(从 C++/CLI 包装器加载 lib))什么是最好的解决方案?链接:msdn.microsoft.com/en-us/library/30c674tx(v=vs.80).aspx 和 msdn.microsoft.com/en-us/library/h5f7ck28(v=vs.80).aspx 【参考方案1】:当您看到值0xdddddddd
时,表示some pointer was deleted(VC 将在调试版本中设置该值以帮助您识别这些情况)。你没有告诉我们loggingFilePath
是什么以及Logging
是如何实现的,但我的猜测是loggingFilePath
在某个时候被删除了,Logging
试图在构造函数中访问它的值或虚函数(或初始化列表)。
这也可以解释析构函数中的崩溃 - 您正在删除 m_log
,它可能包含从 loggingFilePath
获得的非法指针。当您尝试再次使用它时,您会遇到同样的崩溃。
【讨论】:
【参考方案2】:当我调用 m_log = new Logging(loggingFilePath)
幕后发生了什么?找出它到底在哪里崩溃。如果您使用 C#,请启用非托管调试。我猜问题出在Logging
构造函数下。
【讨论】:
嗨!非托管调试已启用!应用程序在其中一些析构函数调用(删除 m_smartmaskcmds;删除 m_readerComm;删除 m_log;)中存在错误,但并不总是在 m_log 中!所以我的猜测是调用对象销毁后内存不干净!但我明天也会发布日志类!以上是关于MFC dll 中的访问冲突(用 C++/CLI 包装)从 C# 程序开始的主要内容,如果未能解决你的问题,请参考以下文章
运行使用 /clr 构建的 DLL 的本机 C++ 应用程序时访问冲突
C++/CLI 包装器尝试使用 MFC CObject 继承
本机 C++ 程序在使用 C++/CLI 和 C# 互操作 DLL 启动时崩溃
0x5746723c (msvcr100d.dll) 处最可能的异常: 0xC0000005: 读取位置 0xccccccc8 时发生访问冲突