"Strange"内存泄漏 - TCP 网络
"Strange" memory leaks - TCP Network
我使用boost::asio
的Packet
S构建了很多类TCP网络 - 用于传输。(Packet
的基类是std::vector<char>
)
我以为我已经修复了所有可能的内存泄漏,但是然后我只是在关闭客户端之前就关闭了服务器 - 这不会引起任何问题 - _CrtDumpMemoryLeaks
报告了内存泄漏。因此,我将视觉泄漏检测器添加到了项目中,并检查了这些内存泄漏的位置。
void dumpMemoryLeaks(void) { CrtDumpMemoryLeaks(); }
//and in main:
atexit(dumpMemoryLeaks);
检查回到报告的内存泄漏的线路,这似乎有点...对我来说很奇怪。
我有一个类AsyncAcceptor
,其中我在构造函数启动器列表中分配了new BoostSocket
-RAW指针(适用于正常和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>
的TypEdef。
BoostSocket(BoostSocket &&s)
: _socket(std::move(s._socket))
{ }
视觉泄漏检测器指向此堆栈:
-
AsyncAcceptor::AsyncAcceptManaged
-
OnSocketOpen
-处理程序 - shared_ptr-内存(452)-
explicit shared_ptr(_Ux *_Px)
-
void _Resetp(_Ux *_Px)
也有Smilar"奇怪"报告。
Packet p;
//add data & add Packet to a std::queue
QueuePacket(Packet &&p);
//Inside QueuePacket:
_queue.push(std::move(p));
内存泄漏:
- 队列(111)-
void push(value_type&& _Val)
- Deque(1181)-
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?的正确报告,我似乎找不到导致所有内容的内存泄漏。
如果您担心它是否可能是假阳性,则需要在调试器中的循环中运行程序的"核心逻辑"。一次,在Megabytes上,应该很快确认内存是否泄漏。
关于您程序的实际设计:
我的原始指针经过正确处理,对于我使用智能指针的其他任何东西。
...
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; }
该语句以及我要采样的代码似乎相互矛盾。
一般而言,使用C 11/C 14,通常的建议是永远不要, ever 处理原始指针,并且永远不会使用明确的new
或delete
关键字。显然,没有规则是100%无误的(我建议您在计算机监视器上写的Sharpie),但是在这种情况下,我会说这仍然是真的99.99 ...%的时间。
因此,每次使用原始指针时,您都需要用std::unique_ptr
替换它们(如果它拥有对象)或std::shared_ptr
(如果有多个对象拥有),则。我看到您已经在某些对象中使用了std::unique_ptr
和std::shared_ptr
;确保您正在为指针的全部做此操作。
其次,用适当的std::make_unique
或std::make_shared
替换new
的每一次使用。除非您正在撰写客户删除,否则消除对delete
的任何和所有引用;即使那样,请确保这实际上是您需要的。
第三,要非常小心您的代码语义:
m_Member = std::move(std::shared_ptr<StoredClass>(new StoredClass(shared_from_this()) ) );
作为一般经验法则,没有理由永远"移动" std::shared_ptr
。std::shared_ptr
存在的原因是允许使用指针的安全复制语义,而在移动是适当选择的情况下,编译器通常足够聪明,可以为您弄清楚。此代码本身可能很好(尽管STD ::移动是多余的),但是您可能需要查看其他代码区域。
我不能指出任何可能是罪魁祸首的特定代码(尤其是因为我们在此处没有完整的代码列表),但是如果您解决了所有这些问题,则很可能会解决内存泄漏(S)。
显然插座没有被自动破坏。我通过在处理新套接字/连接的线程后,在循环中手动关闭所有左插座的问题解决了这个问题。
。代码看起来像这样:
//_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
有自己的意见。
未检测到内存泄漏。
视觉泄漏检测器现已退出。
- 是否有一种标准化的方法通过TCP/IP网络发送JPG图像
- 在多台计算机上运行SFML tcp 网络程序
- C++ SFML 网络:无法建立 TCP 连接
- 为什么我的网络 TCP/UDP 实现不起作用?
- Winsock客户端 - 通过TCP/IP4连接到网络摄像机
- "Strange"内存泄漏 - TCP 网络
- 网络传输时间从TCP/IP堆栈
- 使用Boost.ASIO与服务器进行简单的网络tcp通信
- 网络tcp套接字应用程序重试方法
- iOS 上的 TCP 流不会显示在无线网络上
- 用c++实现TCP/Ip网络通信
- Qt TCP/IP通信只能在本地工作,但在网络中会丢失
- 网络游戏的防作弊技术(TCP)
- 我试图使p2p网络在tcp
- TCP套接字能注意到网络中断的异常吗?
- TCP聊天不能在不同的网络中工作
- Qt5绑定多宿主网络TCP套接字
- 使用c++ TCP客户端套接字在特定的网络接口Linux/Unix
- 需要帮助阅读/解析TCP网络代码c++
- C/ c++ Posix tcp/ip网络客户端,只连接到本地主机