0

首先,对不起我的英语:

我设计了一个小库来管理我的程序使用的内存。主要是实现了一种具有内存管理目的的共享对象。我有以下类(我省略了其他不需要的成员和函数来解释我的问题):

  • 一个名为的参数结构packet,它包含一个类型的子对象T和一个计数器:
template<class T>
struct packet
{
   T t;
   unsigned counter;
};
  • 一个名为ptrstack: 的参数类stack,带有一个析构函数delete,当调用它的析构函数时,它会调用堆栈包含的每个指针:
template<typename T>
struct ptrstack : public std::stack<T*>
{
  ~ptrstack()
  {
      while(!this->empty()) {
        delete this->top();
        this->pop();
      }
  }
};
  • pool使用静态参数函数(当然还有其他代码)调用的类,返回对 a 的引用ptrstack
class pool
{
   template<class T>
   using stack_tp = ptrstack<packet<T> >;

public:
   template<class T>
   static stack_tp<T>& get()
   {
     static stack_tp<T> pool;

     return pool;
   }
};
  • 最后是参数类shared_obj
template<typename T>
class shared_obj
{ /* Members (see below) */ };
  • 用户类继承shared_obj
struct internals_t; // definition in a .cpp source code (pImpl idiom).

// `shared_obj` uses only pointer to its type parameter.
class user_t : public shared_obj<internals_t>
{
  // member functions accessing its internal pointer. 
  // `user_t` is very light. It only mantains a pointer, but it could be used as
  // a common object.
  // moreover, I can work with dynamic objects without using new and delete
  // since the memory is managed by shared_obj
};

构造、分配/复制和销毁基本上执行以下操作:

  • 每次shared_obj<T>想要创建一个新的时,packet<T>*都会在堆中创建一个。
  • 每次shared_obj<T>复制 a 时,其关联数据包的计数器都会递增。
  • 每次shared_obj<T>调用 a 的析构函数时,其关联数据包的计数器都会递减。
  • 如果其关联数据包的计数器达到 0,则其关联指针通过以下方式压入堆栈:
pool::get<T>().push(ptr);
  • 所以,我重新定义了这个列表的第一点:当packet<T>*要创建一个新的,并且其类型的池为空时,在堆中创建一个新的数据包。如果池不是空的,我使用 new 的“就地”版本:
new (pool::get<T>().top()) T(args);
pool::get<T>().pop();

因此,程序退出时会委托销毁,并且所有创建的内存都可以重用。

足够的解释!

我的问题是:我需要任何其他类型为“ user_t”的静态对象(实际上,不同类型的不同对象继承shared_obj),但它们中的任何一个都会产生内存泄漏,我这样做的原因如下:

  • 该静态对象是在创建其关联池之前创建的,因为packet_pool.get<T>()对于每种类型的定义都是在定义之后实例化的:模板定义在第一个使用指针中被实例化为具体类型,而不是在模板被写入的位置。因此,我的文件中的词汇顺序与我的翻译单元中的定义顺序不同。
  • 结果,我的静态对象在其关联的池之后被破坏,因为静态对象以其构造的相反顺序被删除,并且与其翻译单元的定义顺序一致。
  • 当该静态对象被破坏时,其关联的计数器达到 0,并尝试将它们推入其破坏池中。这会引发崩溃。

我的疑问最终如下:

  • 翻译单元中实例化模板函数的具体“定义顺序”是什么?我的假设正确吗?

这里有一个平行的问题:

  • 问题是否也与池是本地静态函数或“get”函数本身内联(因为它是在其类中定义的函数)这一事实有关?pools我的意思是,每个“池”(每个堆栈)是否具有内部链接,并且对于不同翻译单元中的相同类型,我是否有不同的链接?
4

0 回答 0