为什么通过 unique_ptr 创建的内存在调用 reset() 时没有被正确删除?

Why is the memory created via unique_ptr not being deleted properly when reset() is called?

我有一个应用程序可以快速接收数据包,每次它接收数据包时,都会创建一些对象来处理它们,我正在使用 std::unique_ptr.

创建对象

出于某种原因,它们似乎没有得到正确清理,因为我可以看到应用程序的内存使用量不断上升。

我拍了一张快照以查看分配的来源,正如预期的那样

这是创建这些 PacketInPacketHeader 对象的代码

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();

}

PacketIn

class IPacketIn {
public:
    IPacketIn() {
        m_packetHeader = std::make_unique<PacketHeader>();
    }

    ~IPacketIn() {
        m_packetHeader.reset();
    }

    void ReadHeader(std::shared_ptr<Stream> stream) {
        m_packetHeader->ReadHeader(stream);
    }

private:
    std::unique_ptr<IPacketHeader> m_packetHeader;
};

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;

我已经逐步完成了代码,似乎调用重置正在清除 unique_ptr 但它实际上是在删除它创建的内存还是我遗漏了什么?


编辑

所以它似乎与 unique_ptr 无关,因为我曾尝试使用 newdelete 来解决同样的问题。

我注意到当 PacketHeader class 有成员变量时会出现问题

std::string m_uuid;
long m_timestamp;
unsigned short m_packetId;

删除这些变量后,问题不再出现。

我已将其缩小为 std::string uuid;。当它出现在 PacketHeader class 中时,它会导致内存增加,但当它被删除时就没问题了。这是为什么?

当对象被销毁时,这些是否以某种方式没有被删除?

是的,是删除内存

请注意,对 reset 的调用都不需要 - 在这两种情况下都将调用指针的析构函数,这将删除内存。

请注意,监视进程内存是判断是否存在内存泄漏的一种非常不可靠的方法。在某种程度上,系统库经常尝试 重用最近释放的内存 - 以减少释放后使用错误的影响。

尝试使用 valgrind 查看是否有实际内存泄漏。

编辑VTT 已阐明 OP 不是 只是监视进程内存,而是使用 VS 内存分析器(这与 valgrind 非常相似)。

事实证明,PacketHeader class 实例的所有权是通过指向缺少虚拟析构函数的基 class IPacketHeader 的指针持有的。因此 std::unique_ptr<IPacketHeader> 无法正确执行清理。