在C ++中检测并清除从dll导入的错误对象

时间:2016-06-16 12:23:26

标签: c++ dll

我有一个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 Iref”上调用delete来清除堆中的对象。

是否有任何方法可以通过CreateIOReader方法检查错误对象的创建,从而将其从可执行源代码中删除

1 个答案:

答案 0 :(得分:2)

对于此问题dynamic_cast无法帮助您。问题是你不知道你的函数的实际返回类型,只是假装它是IOReader*,而它实际上可能是其他东西(即TestWrongClass*)。在别名规则下,这是不允许的。

将此与情况进行对比:

class IBase { ... };
class IOReader : public IBase { ... };
class TestWrongClass : public IBase { ... };

你也知道你的函数返回IBase*。确实,动态演员可以帮助您,因为IOReaderTestWrongClass具有共同的祖先,并且通过IBase*引用是有效的。

我不得不说这是一个奇怪的问题:调用库函数,你不知道可能会返回什么。我建议稍微改变一下设计。你可以(除其他外):

  1. 按照以上
  2. 创建统一层次结构
  3. 让呼叫返回类似std::pair<int, void*>的内容,其中int(或enum)是确定返回内容的可靠方式,之后您可以{{1} reinterpret_cast
  4. 如果选择方法1,然后解决删除问题,可以在void*接口添加destroy()之类的函数,这会导致库删除对象(注意:它是错误的想法IBase自己由外部图书馆提供给你的对象。

    如果您选择方法2,那么也许您可以拥有像delete这样的库函数,如果您收到的不是您想要的内容,您可以传递void destroy(int, void*)的成员。然后,库可以使用这些将std::pair强制转换为正确的内容以在内部删除它。