我有很多类构建一个TCP网络--使用boost::asio,使用Packet进行传输。( Packet的基类是std::vector<char>)
我以为我已经修复了所有可能的内存泄漏,但是在关闭客户机之前,我只是简单地关闭了服务器--这不会造成任何问题-- _CrtDumpMemoryLeaks报告了内存泄漏。因此,我将视觉泄漏检测器添加到项目中,并检查了这些内存泄漏发生的位置。
void dumpMemoryLeaks(void) { CrtDumpMemoryLeaks(); }
//and in main:
atexit(dumpMemoryLeaks);查回VLD报告内存泄漏的线路,似乎有点.对我来说很奇怪。
我有一个类AsyncAcceptor,在构造函数初始化列表中分配new BoostSocket -原始指针(用于普通套接字和SSL套接字的包装器)。在AsyncAcceptor的析构函数中,如果原始指针有效,则正确删除它。
_acceptor = new AsyncAcceptor(service, bindIP, port); //No memory leak for this pointer
//...
_acceptor->AsyncAcceptManaged(_OnSocketAccept); //Function pointer在AsyncAcceptManaged内部,服务器正在等待连接并传递另一个指针--一个内存泄漏。
//Set socket properties
//Call handler function passed as parameter
handler(_socket); //Raw pointer passed to handler
_socket = nullptr;
_socket = new BoostSocket(_acceptor.get_io_service()); //with ctx for SSL, if defined
//If the acceptor is not closed, it calls `AsyncAcceptManaged` again.现在转到处理程序函数。
void OnSocketOpen(BoostSocket *sock)
{
//set additional socket options and check for error
//Note: SocketType is template parameter of class - allowing different socket types
std::shared_ptr<SocketType> newSocket(new SocketType(sock));
delete sock;
sock = nullptr;
}SocketType总是有一个基类,它对BoostSocket *具有相同的构造函数重载。
Socket(BoostSocket *socket)
: _socket(std::move(*socket))
{
//...
}在BoostSocket中,成员_socket是一个std::unique_ptr<SocketType>,其中SocketType是一个tcp::socket或boost::asio::ssl::stream<tcp::socket>的类型。
BoostSocket(BoostSocket &&s)
: _socket(std::move(s._socket))
{ }可视检漏器指向此堆栈:
AsyncAcceptor::AsyncAcceptManagedOnSocketOpen -处理程序explicit shared_ptr(_Ux *_Px)void _Resetp(_Ux *_Px)也有笑脸“奇怪”的报道。
Packet p;
//add data & add Packet to a std::queue
QueuePacket(Packet &&p);
//Inside QueuePacket:
_queue.push(std::move(p));内存泄漏:
void push(value_type&& _Val)void push_back(value_type&& _Val)内存泄漏(_socket是std::unique_ptr):
BoostSocket(boost::asio::io_service &ioService)
: _socket(new SocketType(ioService)) //<--- here
{ }内存泄漏(m_Member是std::shared_ptr):
m_Member = std::move(std::shared_ptr<StoredClass>(new StoredClass(shared_from_this()) ) );大内存泄漏(_readBuffer是std::vector<char>):
_readBuffer.resize(static_cast<std::size_t>(DataUnits::DATA_UNIT_MB) * 5); //resize to 5 MB我假设最后一次内存泄漏是由于没有像内存泄漏报告那样正确地破坏套接字造成的。然而,我无法想象问题可能是什么。我的原始指针被正确地处理,对于其他任何东西,我都使用智能指针。
视觉泄漏检测器检测到17个内存泄漏(5244907字节)。
--这是VLD的正确报告吗? --我似乎找不到导致所有问题的内存泄漏。任何提示或解决方案都很感激。
发布于 2016-06-22 09:40:15
显然插座没有被自动销毁。我已经通过在循环中手动关闭所有左套接字来解决这个问题,在停止并加入处理新套接字/连接的线程之后,它完成了它们的更新循环。
代码如下:
//_sockets - std::set with std::shared_ptr<SocketType>
if (_stopped) //std::atomic
{
for (i = _sockets.begin(); i != _sockets.end();)
{
if ((*i)->IsOpen() && (*i)->IsSocketOpen())
{
(*i)->CloseSocket();
SocketRemoved(*i); //Do work when client gets disconnected
--_connections; //std::atomic
}
_sockets.erase(i++);
}
}VLD不报告任何内存泄漏,尽管_CrtDumpMemoryLeaks有自己的看法。
没有检测到内存泄漏。 视觉检漏仪现在出来了。
发布于 2016-06-21 21:48:24
如果您担心它是否为假阳性,则需要在调试器中的循环中运行程序的“核心逻辑”。一次以兆字节计算,这应该很快就能确认内存是否泄漏了。
至于你的节目的实际设计:
我的原始指针被正确地处理,对于其他任何东西,我都使用智能指针。 ..。 void OnSocketOpen(BoostSocket * sock ) {//设置附加套接字选项并检查错误//注意: SocketType是类的模板参数-允许不同的套接字类型std::shared_ptr newSocket(新的SocketType(sock));删除sock;sock= nullptr;}
这句话,以及我正在取样的代码,似乎彼此不一致。
通常,在C++11/C++14中,通常的建议是从不,处理原始指针,处理显式new或delete关键字。很明显,没有一条规则是100%正确的(我建议你在你的电脑显示器上用锐利写),但在这种情况下,我会说它仍然是正确的99.99%.
因此,每次处理原始指针时,您要么希望用std::unique_ptr (如果它拥有对象)替换它们,要么希望使用std::shared_ptr (如果多个对象拥有它)替换它们,如果您还没有这样做。我看到您已经将std::unique_ptr和std::shared_ptr用于您的一些对象;请确保您正在为所有指针执行此操作。
其次,将new的每次使用替换为适当的std::make_unique或std::make_shared。除非您正在编写客户删除器,否则删除对delete的任何和所有引用;即使这样,也要确保这确实是您所需要的。
第三,要非常小心代码的语义:
m_Member = std::move(std::shared_ptr<StoredClass>(new StoredClass(shared_from_this()) ) );作为一般的经验法则,没有理由“移动”一个std::shared_ptr。std::shared_ptr存在的原因是为了允许指针的安全复制语义,而在移动是适当选择的场景中,编译器通常足够聪明,可以为您解决这个问题。这段代码本身可能很好(尽管std::move是多余的),但是您可能需要查看其他代码区域。
我不能指出任何可能是罪魁祸首的特定代码(特别是因为这里没有完整的代码清单),但是如果您修复了所有这些问题,它很可能会修复内存泄漏。
https://stackoverflow.com/questions/37923384
复制相似问题