第二个dll中的静态实例的破坏者未被调用
Destructor of static instance in second dll not being called
情况
我无法在Librarya上更改loadLibrary的外部库(Library External)。成功加载它后,它调用导出的函数AEXPORT,该功能将指针返回ClassA,这是一个静态实例。在AEXPORT返回之前,它也通过LoadLibrary加载库,称为LibraryB。在成功加载后,它调用导出的函数bexport,然后将指针返回到静态实例classb。
重要
LibraryA是一个C DLL,使用VS2012 XP工具编译,LibraryB是C /CLI DLL,也使用VS2012 XP工具编译。
所有库都共享其他一些库,这些库仅定义了Clasta和ClassB需要从哪些库中得出的,以了解Aexport和Bexport返回的指针。它们只不过是存根,在这个问题中无关紧要(只有纯虚拟功能,没有字段,并且在ctor/dtor中什么也没有做)。
结果
当Library External通过程序退出卸载时,它会在LibraryA上调用Freelibrary。这成功称为" classa"的驱动器,后者又释放了图书馆库。但是,ClassB的破坏者永远不会以某种方式运行。
所需结果
有classB destructor run
classa.h
#include <StubA.h>
class StubB;
class ClassA: public StubA
{
public:
ClassA();
~ClassA();
bool Initialize();
static ClassA &GetInstance()
{
static ClassA INSTANCE;
return INSTANCE;
}
private:
ClassA(ClassA const &);
void operator=(ClassA const&);
HMODULE wrapperModule;
StubB *wrapperPlugin;
};
classa.cpp
#include "ClassA.h"
#include <Windows.h>
// typedef WrapperPlugin *(*WrapperPluginInitType) (); This is normally in shared library
static const wchar_t *WRAPPER_MODULE_NAME = L"LibraryB.dll";
static const char *WRAPPER_MODULE_INIT_FUNCTION_NAME = "BExport";
ClassA::ClassA() :
wrapperModule(NULL),
wrapperPlugin(NULL)
{
}
ClassA::~ClassA()
{
if (this->wrapperModule != NULL)
{
FreeLibrary(this->wrapperModule);
}
}
bool CSharpBridge::Initialize()
{
this->wrapperModule = LoadLibraryW(WRAPPER_MODULE_NAME);
if (this->wrapperModule == NULL)
{
return false;
}
WrapperPluginInitType wrapperPluginInit = reinterpret_cast<WrapperPluginInitType>(GetProcAddress(this->wrapperModule, WRAPPER_MODULE_INIT_FUNCTION_NAME));
if (wrapperPluginInit == NULL)
{
return false;
}
this->wrapperPlugin = wrapperPluginInit();
if (this->wrapperPlugin == NULL)
{
return false;
}
return true;
}
extern "C"
{
__declspec(ddlexport) StubA *AExport()
{
if (!ClassA::GetInstance().Initialize())
{
return NULL;
}
return &ClassA::GetInstance();
}
}
classb.h
#include <StubB.h>
class ClassB : public StubB
{
public:
ClassB ();
~ClassB ();
static ClassB &GetInstance()
{
static ClassB INSTANCE;
return INSTANCE;
}
private:
ClassB (ClassB const &);
void operator=(ClassB const&);
};
classb.cpp
#include "ClassB.h"
#include <Windows.h>
#include <iostream>
#include <fstream>
ClassB::ClassB()
{
std::ofstream myfile;
myfile.open("C:\Users\USERNAME\Desktop\test1.txt");
myfile << "ClassB::ClassBrn";
myfile.close();
}
ClassB::~ClassB()
{
std::ofstream myfile;
myfile.open("C:\Users\USERNAME\Desktop\test3.txt");
myfile << "ClassB::~ClassBrn";
myfile.close();
}
extern "C"
{
__declspec(dllexport) StubB *WrapperInit()
{
std::ofstream myfile;
myfile.open("C:\Users\USERNAME\Desktop\test2.txt");
myfile << "WrapperInitrn";
myfile.close();
return &ClassB::GetInstance();
}
}
现在,我100%确定了Classa ctor/dtor被称为classa ctor/dtor,这是由于某些库外部功能提供了一些文本确认。而且我似乎已经获得了test1.txt和test2.txt生成的。但不是test3.txt。
之后,我仍然需要创建对c#dll和"破坏" classB被破坏时的托管引用。
看来,您无法在不受管理的库管理的库上使用Freelibrary。由于托管库将启动非管理图书馆对此一无所知的应用程序。AppDomain使图书馆保持活力,因此毁灭者从未运行过。看到此答案。
调用未管理到托管的东西仍然需要特别注意,因为不这样做会导致例外:0xc0020001:字符串绑定无效!看到这个。我为解决该问题所做的工作是在ClassB范围内具有静态实例,并使用ClassB :: getInstance中的新操作员初始化它。否则,它根本不会初始化。然后,我将classB ::清理删除。但是,重要的是用#pragma托管(推送,关闭)和#Pragma Managed(POP)标记整个类(标题和源文件)。
。要仍然能够调用托管方法/类,您必须在源文件中制作一个函数,该函数被#pragma托管(push,on)和#pragma Managed(POP)包围。然后,您可以从非托管类调用此功能。这对我来说仍然很奇怪,因为该功能也是管理的吗?
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 函数调用中参数的顺序重要吗
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在c++类上调用void函数
- 为什么 std::unique 不调用 std::sort?
- 调用专用模板时出错"no matching function for call to [...]"
- 选择要调用的构造函数
- 在销毁派生成员之前,在破坏者中调用共同功能
- 为什么我的破坏者只称呼一次,而不是在删除(a)调用上
- 即使在明确调用破坏者后,对象自动破坏也是如此
- 在C 中调用delete []内部破坏者
- 编译器如何处理基类破坏者在派生的破坏者中调用
- 不调用C 破坏者
- 第二个dll中的静态实例的破坏者未被调用
- 在C 中调用破坏者
- 琐碎的破坏性和调用破坏者的必要性