代码之家  ›  专栏  ›  技术社区  ›  Satbir

在运行时投射指针[非常重要的scnerio]

c++
  •  0
  • Satbir  · 技术社区  · 15 年前

    我必须修复一个典型的内存泄漏,问题如下:

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

    从客户机我得到一个map type类型的映射,其中response对象为map->second,因为response对象包含一个空指针。

    请注意:响应类不知道哪些类型的数据已设置为void指针,而且我不能修改响应类来执行此操作,因为它是一个遗留代码,具有很大的影响:(

    现在使用map->首先,我称之为标记,

    在运行时使用这个标记,使用这个标记,我了解了任何类。

    现在response::dataptr与anyClass::datatype相同

    但是:

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

    请指导我如何将空指针强制转换为与anyClass::datatype相同的类型并释放它

    3 回复  |  直到 15 年前
        1
  •  1
  •   sdg    15 年前

    考虑到您提到了“遗留”代码,但可能有一些修改的自由,我可能建议将提供给您的映射的任何接口扩展到包含一个自由的ing函数。

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

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

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

    祝你好运

        2
  •  1
  •   progician    15 年前

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

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

    这样,您就不需要“tag”成员,除非您希望用一个大的“switch”语句手工操作。在这种情况下,我可以建议使用标记成员中typeid(anyclass.name()的crc计算。

    ——编辑: 在没有这个问题的情况下,还有另一种方法来存储这些对象,我想说,Boost::任何或类似的功能都可以解决您的问题。如果您将数据存储在BoostAny而不是void*指针中,那么您可以以最小的影响更改旧代码。如果从映射中删除一个条目,它将删除boost::any的内部值。这应该能解决问题。

        3
  •  0
  •   ovanes    15 年前

    如果您的标签是连续的,那么您可以构建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);
    

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

    如果标记不是连续的,您将需要使用map或smth。类似的,这涉及到非恒定的复杂性。

    希望能有所帮助,
    奥凡内斯

    另外,如果您决定更改响应,请查看boost::variant。这正是您需要的,如果允许您进行常规编程;)