Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 未调用第二个dll中静态实例的析构函数_C++_C++ Cli - Fatal编程技术网

C++ 未调用第二个dll中静态实例的析构函数

C++ 未调用第二个dll中静态实例的析构函数,c++,c++-cli,C++,C++ Cli,形势 无法更改的外部库(LibraryExternal)调用LibraryA上的LoadLibrary。成功加载后,它调用导出的函数AExport,该函数返回指向ClassA的指针,ClassA是一个静态实例。在AExport返回之前,它也通过LoadLibrary(称为LibraryB)加载库。成功加载后,它调用导出的函数BExport,该函数反过来返回指向静态实例ClassB的指针 重要 Labalya是用VS201XP工具编译的C++ DLL,而LabyAb是用VS201XP工具编译的C

形势

无法更改的外部库(LibraryExternal)调用LibraryA上的LoadLibrary。成功加载后,它调用导出的函数AExport,该函数返回指向ClassA的指针,ClassA是一个静态实例。在AExport返回之前,它也通过LoadLibrary(称为LibraryB)加载库。成功加载后,它调用导出的函数BExport,该函数反过来返回指向静态实例ClassB的指针

重要

Labalya是用VS201XP工具编译的C++ DLL,而LabyAb是用VS201XP工具编译的C++/CLI DLL。 所有库共享一些其他库,这些库只定义ClassA和ClassB需要从中派生的内容,以便理解AExport和BExport返回的指针。它们只不过是存根,在这个问题上无关紧要(只有纯虚拟函数,没有字段,在ctor/dtor中也没有任何操作)

结果

当LibraryExternal通过程序退出卸载时,它调用LibraryA上的FreeLibrary。这成功地调用了ClassA的析构函数,从而释放了LibraryB库。但是ClassB的析构函数从未以某种方式运行过

期望的结果

运行ClassB析构函数

A.h级

#包括
B类;
A类:公共存根
{
公众:
类别a();
~ClassA();
bool初始化();
静态ClassA&GetInstance()
{
静态ClassA实例;
返回实例;
}
私人:
ClassA(ClassA常数&);
void运算符=(ClassA常量&);
模块包装器模块;
StubB*包装插件;
};
ClassA.cpp

#包括“ClassA.h”
#包括
//typedef WrapperPlugin*(*wrapperplugininitype)();这通常在共享库中
静态常量wchar_t*包装器_模块_NAME=L“LibraryB.dll”;
静态常量字符*包装器模块初始化函数;
ClassA::ClassA():
包装器模块(空),
包装器插件(空)
{
}
ClassA::~ClassA()
{
如果(此->包装器模块!=NULL)
{
FreeLibrary(此->包装器模块);
}
}
boolcharpbridge::Initialize()
{
此->包装器模块=LoadLibraryW(包装器模块名称);
if(this->wrapperModule==NULL)
{
返回false;
}
WrapperPlugininitype wrapperPluginInit=reinterpret_cast(GetProcAddress(this->wrapperModule,WRAPPER_模块_INIT_函数_名称));
if(wrapperPluginInit==NULL)
{
返回false;
}
此->wrapperPlugin=wrapperPluginInit();
if(this->wrapperPlugin==NULL)
{
返回false;
}
返回true;
}
外部“C”
{
__declspec(ddlexport)StubA*AExport()
{
如果(!ClassA::GetInstance().Initialize())
{
返回NULL;
}
return&ClassA::GetInstance();
}
}
B.h类

#包括
B类:公共存根B
{
公众:
b类();
~ClassB();
静态类b&GetInstance()
{
静态ClassB实例;
返回实例;
}
私人:
B类(B类常数&);
void运算符=(ClassB常量&);
};
类别b.cpp

#包括“ClassB.h”
#包括
#包括
#包括
ClassB::ClassB()
{
std::流myfile;
myfile.open(“C:\\Users\\USERNAME\\Desktop\\test1.txt”);

myfile您似乎无法在从非托管库管理的库上使用FreeLibrary。因为托管库将启动非托管库不知道的AppDomain。AppDomain使库保持活动状态,因此从未运行析构函数。请参阅答案

将某个对象从非托管调用为托管仍然需要特别注意,因为如果不这样做,将导致异常:0xC002001:字符串绑定无效!请参阅。我所做的是在ClassB作用域中使用静态实例,并在ClassB::GetInstance中使用新运算符对其进行初始化。否则它将不可用不需要初始化。然后我创建了一个函数ClassB::CleanUp,在其中我删除了它。但是,重要的是要用#pragma-managed(push,off)和#pragma-managed(pop)标记整个类(头文件和源文件)为非托管


要仍然能够调用托管方法/类,您必须在源文件中创建一个函数,其中包含#pragma managed(push,on)和#pragma managed(pop)。然后,您可以从非托管类调用此函数。这对我来说仍然很奇怪,因为该函数也是托管的?

至少要解释一下为什么您否决了此函数,以便我下次可以做得更好。。嗯,我知道是怎么回事。当您要求志愿者投入他们的空闲时间来帮助您时,最起码的礼貌是发布代码至少,他们可以编译并运行来重新处理问题。这段代码既不编译也不运行。处理起来相当简单,只需自己编译并运行即可。
#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;
};
#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();
    }
}
#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&);
};
#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::ClassB\r\n";
    myfile.close();
}

ClassB::~ClassB()
{
    std::ofstream myfile;
    myfile.open("C:\\Users\\USERNAME\\Desktop\\test3.txt");
    myfile << "ClassB::~ClassB\r\n";
    myfile.close();
}

extern "C"
{
    __declspec(dllexport) StubB *WrapperInit()
    {
        std::ofstream myfile;
        myfile.open("C:\\Users\\USERNAME\\Desktop\\test2.txt");
        myfile << "WrapperInit\r\n";
        myfile.close();

        return &ClassB::GetInstance();
    }
}