在运行时[非平凡场景]中转换指针

时间:2009-09-24 12:19:27

标签: c++

我必须修复典型的内存泄漏,问题就是这样:

typedef std::map<unsigned long,Response> mapType;
class Response
{
public:
 void *dataPtr;
 unsigned long tag;
}

class anyClass
{
 public::

  DataType x;
}

从客户端我得到一个Type mapType的地图,其中Response对象为map-&gt; second,As Response对象包含一个void指针。

请注意:响应类不知道哪些类型的数据已设置为void指针,另外我无法修改Response类来执行此操作,因为它是遗留代码并且影响很大:(

现在先使用map-&gt;,我称之为Tag,

使用此标记在运行时使用此标记,我开始了解类anyClass。

现在,Response :: dataPtr被asclass :: DataType

可是:

因为类anyClass是N类型中的一个,所以anyClass :: DataType对于我在运行时才知道的每个类都不同。

请指导我如何构建一个void指针,以便对anyClass :: DataType进行类型化,并且可以释放它

3 个答案:

答案 0 :(得分:1)

首先,我不知道为什么在内存泄漏问题时需要将这些指针强制转换为原始类型。您可以在任何地方删除void *指针。 其次,与标记相比,您可以将指针转换为具有简单条件语句的特定类型到某个特定类型,但是您需要在给定上下文中具有该指针的特定代码,因此在这个意义上没有足够的信息在这里解决问题。

但是,如果您的响应有某种行为,请将其称为“进程”,您可以使用带有虚函数的继承将所需行为绑定到您的对象。这基本上是虚方法的定义,所以使用它们,即使你需要为此重构旧代码。如果对象处理存在问题,那么它是虚拟析构函数的问题,因此基类应该定义一个虚拟dtor,并且使用dynamic_cast(ptr)可以在转换时为您提供一些类型安全性。

通过这种方式,您不需要'tag'成员,除非您想通过一个大的'switch'语句手动执行此操作。在这种情况下,我可以建议使用标记成员中的typeid(AnyClass).name()进行crc计算。

- 编辑: 还有另一种方法来存储这些对象而没有这个问题,我会说一个boost ::任何或类似的功能可以解决你的问题。如果您将数据存储在boost any而不是void *指针中,则可以以最小的影响更改遗留代码。如果从地图中删除一个条目,它将删除boost :: any的内部值。这应该可以解决问题。

答案 1 :(得分:1)

鉴于您提到“遗留”代码,但可能有一些修改自由,我可能会建议您提供的任何界面都可以扩展为包含免费功能。

然后它可以应用与首先创建对象时相同的类型逻辑。

如果这是不可能的,那么你可能最终会得到一个case语句,并且会重新解释一些类似下面的伪代码:

  switch (type ) {
    case Type1:
      delete reinterpret_cast<Type1Class*>(ptr);
      break;
    case Type2:
      ...

祝你好运

答案 2 :(得分:0)

如果你的标签是顺序的,你可以建立smth。就像一个带有函数对象或其处理程序的函数指针的数组:

template<class T>
void deleteType(void* p)
{
   delete reinterpret_cast<T*>(p);
}

typedef void (deletePtr)(void*);
deletePtr handlers_[] =
{ &deleteType<int> //means: accessed by tag with value 0
, &deleteType< vector<int> > // tag with value 1
, ...
};

//somewhere later:
handlers_[response->tag](response->dataPtr);

此解决方案要求您了解可能存储在响应中的所有类型。

如果标签不是连续的,则需要使用地图或smth。类似的,涉及非恒定的复杂性。

希望有所帮助,
Ovanes

P.S。但如果您决定更改响应,请查看boost :: variant。如果您被允许一般编程,那么这正是您所需要的;)