C++ 为什么在调用reset()时,通过unique_ptr创建的内存没有被正确删除?
我有一个快速接收数据包的应用程序,每次它接收数据包时,都会创建一些对象来处理它们,对于对象创建,我使用的是C++ 为什么在调用reset()时,通过unique_ptr创建的内存没有被正确删除?,c++,memory,unique-ptr,C++,Memory,Unique Ptr,我有一个快速接收数据包的应用程序,每次它接收数据包时,都会创建一些对象来处理它们,对于对象创建,我使用的是std::unique_ptr 由于某些原因,它们似乎没有得到适当的清理,因为我可以看到应用程序的内存使用率不断上升 我拍了一张快照,看看分配是从哪里来的,这和预期的一样 下面是创建这些PacketIn和PacketHeader对象的代码 while (!server->BufferEmpty()) { std::shared_ptr<Stream> i
std::unique_ptr
由于某些原因,它们似乎没有得到适当的清理,因为我可以看到应用程序的内存使用率不断上升
我拍了一张快照,看看分配是从哪里来的,这和预期的一样
下面是创建这些PacketIn
和PacketHeader
对象的代码
while (!server->BufferEmpty()) {
std::shared_ptr<Stream> inStream = std::make_shared<Stream>();
std::vector<unsigned char> buffer = inStream->GetBuffer();
std::size_t n = server->receive(boost::asio::buffer(buffer),
boost::posix_time::milliseconds(-1), ec);
if (ec)
{
std::cout << "Receive error: " << ec.message() << "\n";
}
else
{
std::unique_ptr<IPacketIn> incomingPacket = std::make_unique<IPacketIn>();
incomingPacket->ReadHeader(inStream);
std::cout << "Received a buffer! ";
//std::cout.write(buffer, n);
std::cout << "\n";
incomingPacket.reset();
}
++packetsRead;
inStream.reset();
}
PacketHeader
class PacketHeader : public IPacketHeader {
public:
PacketHeader() {
}
~PacketHeader() {
}
void ReadHeader(std::shared_ptr<Stream> stream) override {
//m_uuid = stream->ReadUUID(10);
//m_timestamp = stream->ReadInt64();
//m_packetId = stream->ReadShort();
}
private:
std::string m_uuid;
//long m_timestamp;
//unsigned short m_packetId;
删除这些变量后,问题不再发生
我已经把它缩小为std::string uuid代码>。当PacketHeader
类中存在此项时,它会导致内存上升,但当它被删除时,它是正常的。为什么会这样
当对象被销毁时,它们是否没有被删除?是的,它正在删除内存
请注意,对reset
的调用都不需要-指针的析构函数将在这两种情况下被调用,这将删除内存
请注意,监视进程内存是判断内存是否泄漏的一种非常不可靠的方法。在某种程度上,系统库经常尝试不重用最近释放的内存,以减少释放bug后使用的影响
尝试使用valgrind查看是否存在实际内存泄漏
Edit:澄清了OP不仅仅是监视进程内存,而是使用VS内存探查器(与valgrind非常类似)。事实证明,PacketHeader
类实例的所有权是通过指向基类IPacketHeader
的指针来持有的,而基类IPacketHeader
缺少虚拟析构函数。因此,std::unique\u ptr
无法正确执行清理。为什么要重置它?不需要调用reset-在声明ptr的块结束后,它将从堆栈中弹出,并调用其析构函数。(RAII)ReadHeader是否分配?此外,您使用什么工具链?可能有某种泄漏检测工具。@BenjaminMurer只提供成员变量,当对象被删除时,这些变量应该被清除,Stream
中的函数目前什么都不做。啊,事实上,@CrisLuengo提出了一个非常好的观点。为什么要使用智能指针呢?你可以把它放在堆栈上(如果必须的话,还可以在对象内部分配内存)。查看或iPacktheader
是否有虚拟析构函数?如果没有,则std::unique_ptr
将无法正确执行清理。我当前正在使用Windows,valgrind是否不适用于此平台?使用VS memory profiler是检测内存泄漏的可靠方法。你的评论在这方面有误导性。@VTT啊!我不知道这是VS内存分析器中的一个图形。我认为它来自于系统监视器(它只报告进程内存)。我会更新。
class PacketHeader : public IPacketHeader {
public:
PacketHeader() {
}
~PacketHeader() {
}
void ReadHeader(std::shared_ptr<Stream> stream) override {
//m_uuid = stream->ReadUUID(10);
//m_timestamp = stream->ReadInt64();
//m_packetId = stream->ReadShort();
}
private:
std::string m_uuid;
//long m_timestamp;
//unsigned short m_packetId;
std::string m_uuid;
long m_timestamp;
unsigned short m_packetId;