我有一个 dll(“so.dll”)定义如下,其中我有一个函数 TestWrongClass,它返回一个指针 到类对象 (TestWrongClass)。
/////// "IOReader.h" //////////////
class IOReader
{
public :
IOReader() {};
virtual ~IOReader() {};
virtual bool open(const std::string &format,
const std::string &fileName, const int mask) = 0;
std::string errorMessage;
};
// "IOReader.h" Ends Here
// ---- so.dll ---- /
//////////////// sio.h ////////////
#ifdef SEIO_EXPORTS
#define SEIO_API __declspec(dllexport)
#else
#define SEIO_API __declspec(dllimport)
#endif
#include <string>
#include "IOReader.h"
class SReaderIO : public IOReader
{
public:
SReaderIO() {};
bool open(const std::string &format,
const std::string &fileName, const int mask)
{
return true;
}
};
class TestWrongClass
{
public:
TestWrongClass() { };
bool open(const std::string &format,
const std::string &fileName, const int mask)
{
return true;
}
};
SEIO_API TestWrongClass* CreateIOReader()
{
TestWrongClass * module = new TestWrongClass();
return module;
}
//// sio.h ends here ///////
//in the main executable I am loading the dll on run time
// and after creating a object of type TestWrongClass,
//I explicitly try to cast it with the wrong object, as follows
/// Main Source //
#include <iostream>
#include <windows.h>
#include "IOReader.h"
int main ()
{
HMODULE hDLL=LoadLibrary(L"sIO.dll");
CreateSealafineReaderFn _funcSelafinCreator = NULL;
_funcSelafinCreator = (CreateSealafineReaderFn) GetProcAddress (hDLL,
"CreateIOReader");
// Method 1
void *Iref = (_funcSelafinCreator)();
IOReader * locReader = NULL;
locReader = reinterpret_cast <IOReader *>(Iref); // but how to check
// that object locReader is not of base type IOReader
// so that I may call delete Iref
// If I try to do as follow, then I get illegal error from compiler
// locReader = dynamic_cast <IOReader *>(Iref); // illegal
// Method 2
try
{
locReader = dynamic_cast <IOReader *>((_funcSelafinCreator)());
// works but how can I check wrong casting and catch exception
} catch (std::bast_cast)
{
// how to clear the object created by CreateIOReader
}
}
//
我做这个过程的原因是检查是否有任何 dll,主程序将从 dll 目录中扫描 可能有一个同名的方法,但是该方法创建的对象的返回指针类型可能不同,这是不希望的。 (在上面提到的情况下,方法是 CreateIOReader)
如果我使用 dynamic_cast,我可以检查 bad_cast 异常,但是该对象已经在 dll 中创建,并且不会被释放,因为我 无权访问 dll 的内部代码。
我使用 reintepret_cast 给出的上述方法有效,但是我无法检查是否返回了正确的对象类型。 如果通过某种方法知道如果转换类型不正确,那么我可以在 Iref 指针上调用 delete“delete Iref”以从堆中清除对象。
有没有什么方法可以检查CreateIOReader方法是否创建了错误的对象,从而将其从可执行源代码中删除
最佳答案
对于这个问题dynamic_cast
帮不了你。问题是您不知道函数的真正返回类型,而只是假装它是 IOReader*
。 ,当它实际上可能是别的东西时(即 TestWrongClass*
)。根据别名规则,这是不允许的。
对比一下情况:
class IBase { ... };
class IOReader : public IBase { ... };
class TestWrongClass : public IBase { ... };
你还知道你的函数返回一个 IBase*
.在这里,动态类型转换确实可以帮助您,如 IOReader
和 TestWrongClass
有共同的祖先,并且通过 IBase*
来引用两者都是有效的.
我不得不说这是一个奇怪的问题:调用库函数时您不知道会返回什么。我建议稍微改变一下设计。您可以(除其他事项外):
- 按照上述创建统一的层次结构
- 让调用返回类似
std::pair<int, void*>
的内容, 其中int
(或enum
)将是确定返回内容的可靠方法,之后您可以reinterpret_cast
void*
如果您选择方法 1,那么要解决您的删除问题,您可以添加类似 destroy()
的函数到 IBase
接口(interface),这会导致库删除对象(注意:delete
自己删除外部库提供给您的对象是个坏主意)。
如果您选择方法 2,那么也许您可以拥有类似 void destroy(int, void*)
的库函数,您可以将 std::pair
的成员传递给它如果您收到的不是您想要的东西。然后库可以使用这些来转换 void*
回到正确的地方在内部删除它。
关于c++ - 在 C++ 中检测并清除从 dll 导入的错误对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37859129/