我应该在哪里释放这个物体?

时间:2011-06-22 06:45:13

标签: c++

void ServerManager::addWork(SocketClient *clientSocket, vector<char> data){
    Work *work = new Work(clientSocket, data);
    m_workHandler->addWork(work);
}

在这里,我创建了Work实例并将工作交给了WorkHandler。

m_workHandler->addWork(work);

此代码将工作插入队列。

这是我的服务器的一部分,如果我长时间运行此代码,那么服务器崩溃时会出现错误,如此

what() std::bad_alloc

我在线查看,这是一条错误消息,显示没有可用的内存空间。所以我意识到在完成使用它之后我没有释放工作对象。

所以我想知道我应该在哪里释放工作对象。

void ServerManager::addWork(SocketClient *clientSocket, vector<char> data){
    Work *work = new Work(clientSocket, data);
    m_workHandler->addWork(work);
    delete work;
}

我可以这样做吗?如果我传递工作实例,那么它会增加引用计数?

void WorkHandler::workLoop(){
    printf("WorkHandler::workLoop, called\n");

    while(m_workHandlerRun){
        Work *work = getWork();
        char *pdata = work->getVPointer();

        unsigned char type = pdata[0];

        printf("WorkHandler::workLoop, type %d\n", type);

        Packet *packet = m_packetFactory->createInstance(static_cast<PACKET_TYPES>(type));
        packet->fromByte(pdata);

        delete work;
    }
}

这是我处理工作的代码....我应该在这里删除工作实例还是两个地方?提前谢谢......

6 个答案:

答案 0 :(得分:1)

如果您要将作品插入队列并且尚未完成处理,则您不希望在将其添加后立即将其删除。

您要做的是仔细查看您的代码,当您不再需要周围的对象时,请将其删除。这通常是在您在WorkHandler中完成它并且已经安全地从队列中删除之后。

答案 1 :(得分:1)

addWork()中删除不会 - 您刚刚添加了对象,其他一些代码可能会开始访问它。如果你delete它现在遇到了未定义的行为。 workLoop()是一个更好的地方 - 你已完成对象的所有工作,看起来不再需要了,所以你可以在这里删除它。

答案 2 :(得分:1)

完成后,您应该释放对象(delete)。您不应该删除相同的对象两次。一旦你delete一个对象,你就不应该尝试通过其他指针来访问它。

请记住,C ++没有任何垃圾回收。所以没有引用计数。如果您选择newdelete,则需要自己手动处理分配和释放。否则,您可以使用auto_ptr

答案 3 :(得分:1)

  1. 如果你首先删除work,你很可能会尝试从指针读取崩溃而不是指向正确的对象,但是标准说它是UB,所以你可能会程序不会崩溃。
  2. 如果您在第二位删除work则可以。
  3. 但更好的解决方案是将work放置到某个智能指针上,该指针会在销毁后自动将其删除(在while中离开workloop循环后)。请使用boost::shared_ptr<>

答案 4 :(得分:1)

根据您的第二位代码判断,内存泄漏可能实际上来自Packet分配,因为Work实例正在被删除的地方看起来是正确的(在{ {1}}, workLoop)。但是,如果没有看到更多代码,我无法确定。

C ++中的分配没有引用计数,因此您应该在使用它时删除addWork实例。如果你事先删除它,它就消失了:使用那个指针,结果将是未定义的(可能有效,可能不会)。如果你不删除它,它将泄漏(如你所见)。

您应该重构代码以使用智能指针 - 请查看std :: unique_ptr&lt;&gt;和std :: shared_ptr&lt;&gt; (或boost :: scoped_ptr&lt;&gt;和boost :: shared_ptr&lt;&gt;)。他们将帮助确保事情真正被删除时删除:

Work

答案 5 :(得分:0)

,这是灾难性的。 work指针仍在使用中,您delete正在使用它。这使它成为一个悬垂的指针。引用悬空指针是未定义的行为

如果您不想管理对象的释放,请使用shared_ptr<>或其他智能指针。或者,deleteServerManager::~ServerManager()内,因为您仍然可以在m_workHandler内找到他们的引用。