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;
}
}
这是我处理工作的代码....我应该在这里删除工作实例还是两个地方?提前谢谢......
答案 0 :(得分:1)
如果您要将作品插入队列并且尚未完成处理,则您不希望在将其添加后立即将其删除。
您要做的是仔细查看您的代码,当您不再需要周围的对象时,请将其删除。这通常是在您在WorkHandler中完成它并且已经安全地从队列中删除之后。
答案 1 :(得分:1)
在addWork()
中删除不会 - 您刚刚添加了对象,其他一些代码可能会开始访问它。如果你delete
它现在遇到了未定义的行为。 workLoop()
是一个更好的地方 - 你已完成对象的所有工作,看起来不再需要了,所以你可以在这里删除它。
答案 2 :(得分:1)
完成后,您应该释放对象(delete
)。您不应该删除相同的对象两次。一旦你delete
一个对象,你就不应该尝试通过其他指针来访问它。
请记住,C ++没有任何垃圾回收。所以没有引用计数。如果您选择new
和delete
,则需要自己手动处理分配和释放。否则,您可以使用auto_ptr。
答案 3 :(得分:1)
work
,你很可能会尝试从指针读取崩溃而不是指向正确的对象,但是标准说它是UB,所以你可能会程序不会崩溃。 work
则可以。但更好的解决方案是将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<>
或其他智能指针。或者,delete
在ServerManager::~ServerManager()
内,因为您仍然可以在m_workHandler
内找到他们的引用。