-3

我需要创建稍后由线程处理的类队列。问题是每次我添加对对象的引用时,队列都会为该类分配内存,从而导致巨大的内存泄漏。这也导致程序在退出时挂起。

将 12345678 对 TaskClass 对象的引用添加到 TaskQueue 会导致 137MB 内存泄漏。请注意,调用 queue.pop() 时不会释放内存。

类任务队列:

template <class tjob>
class TaskQueue
{
private:
    std::queue<tjob> _taskqueue;
public:
    TaskQueue()
    {
        //constructor goes here
    }
    //add task to queue
    template < typename Class>
    bool AddTask( Class &PClass)
    {
        _taskqueue.push(PClass);
        return true;
    }
    bool ProcessQueue()
    {
        while (!_taskqueue.empty())
        {
            _taskqueue.front().run();
            _taskqueue.pop();
        }
        return true;
    }
    //run a function pointer
    template < typename Task >
    bool RunTask( Task task){
        task();
        return true;
    }
    //call class entry point member .run
    template < typename Class>
    bool RunClass ( Class& PClass){
        PClass.run();
        return true;
    }
    //return remaining tasks
    int GetRemainingTasks(){
        return _taskqueue.size();
    }
};

类任务类:

class TaskClass 
{
protected:
    int *ptr_x;
public:
    TaskClass() {
        std::cout << "TaskClass Constructor called\n";
        ptr_x = new int(0);
    }
    bool run(){
        *ptr_x = *ptr_x + 1;
        return true;
    }
    bool printx(){
        std::cout << "x is now " << *ptr_x << std::endl;
        return true;
    }
    ~TaskClass(){
        //std::cout << "TaskClass destructor called!\n";
    }
};

主要的:

int main()
{
    TaskClass job1;
    int nojobs = 12345678;
    TaskQueue<TaskClass> TestQueue;
    std::cout << "Preparing Queue... Adding " << nojobs << " tasks.. "; //std::cin.get();
    for (int i=0;i<nojobs;i++)
        TestQueue.AddTask(job1);
    std::cout << "Done!\n"; //std::cin.get();
    std::cout << "Processing Queue... "; 
    TestQueue.ProcessQueue();
    std::cout << "Done!\n"; 
    job1.printx();
    std::cout << "Remaining tasks: " << TestQueue.GetRemainingTasks() << std::endl;
    //std::cin.get(); 
    //exit(0);
    return 0;
}
4

1 回答 1

1

内存泄漏是

ptr_x = new int(0);

因为你永远不会删除那段记忆。至少,您需要在析构函数中删除它,并添加一个深度复制它的复制构造函数。更好的解决方案是将指针替换为简单的

class TaskClass 
{
protected:
    int x;

(尽管我不明白为什么会static像比尔兹的回答那样)。


附带的不当之处:

  1. 不必要的模板:

    template < typename Class>
    bool AddTask( Class &PClass) {
    

    唯一有效的类型Class是类模板参数tjob,那么为什么要模板这个方法呢?为什么需要一个非常量引用你只能复制的东西?

    bool AddTask(tjob const &job) {
        _taskqueue.push(job);
        return true;
    }
    

    更好。对于其他模板化方法也是如此。

  2. 我需要创建类队列

    不,你没有,事实上你不能(我想typeinfo_t如果你真的想要的话,你可以创建一个队列)。您需要创建一个对象队列。幸运的是,这就是您实际所做的,因为调用对象引用PClass并不会使其成为指向类的指针。

    这可能看起来(而且确实是)迂腐,但如果你掌握了正确的术语,通常对每个人来说都会更容易。

于 2013-09-13T11:36:17.243 回答