代码之家  ›  专栏  ›  技术社区  ›  Zuiax

有没有一种方法可以通过队列和带有字符数组的自定义结构来阻止内存泄漏?

  •  2
  • Zuiax  · 技术社区  · 4 月前

    我正在创建一个自定义对象 Message ,然后将其附加到队列中。这将调用复制构造函数;但是,a之后的地址 memmove() 看起来不像我期望的那样匹配。

    代码如下

    #include <iostream>
    #include <queue>
    
    struct Message
    {
      char* data = nullptr;
      size_t size = 0;
    
      Message() = default;
    
      ~Message()
      {
        delete[] data;
      }
    
      Message(const Message& other)
      {
          this->data = new char[other.size];
          this->size = other.size;
    
          memmove(this->data,
                  other.data,
                  this->size);
      }
    };
    
    std::queue<Message> message_queue;
    
    int main()
    {
        Message message;
    
        message.size = 50;
        message.data = new char[message.size];
    
        std::cout << &message.data << std::endl;
    
        message_queue.push(std::move(message));
    
        Message other_message = message_queue.front();
        message_queue.pop();
    
        std::cout << &other_message.data << std::endl;
    
        return 0;
    }
    

    我想知道为什么将此项目推送到队列并获取其内存地址是不同的。地址不应该相同吗?如果我不定义,这是内存泄漏吗 ~Message() delete[] data;

    编辑:如果我不在析构函数上删除,这肯定是内存泄漏。但是为什么记忆不在同一个位置呢?

    编辑2:

    我现在上课如下:

    #include <iostream>
    #include <queue>
    #include <cstring>
    #include <utility>
    
    struct Message
    {
        char* data = nullptr;
        size_t size = 0;
    
        Message(size_t in_size)
        {
            size = in_size;
            data = new char[size];
        }
    
        ~Message()
        {
            delete[] data;
        }
    
        Message(const Message& other)
        {
            std::cout << "Message(const Message& other)\n";
    
            this->size = other.size;
            this->data = new char[this->size];
    
            memmove(this->data,
                    other.data,
                    this->size);
        }
    
        Message& operator=(const Message& other)
        {
            std::cout << "Message& operator=(const Message& other)\n";
    
            if (this == &other)
            {
                return *this;
            }
    
            Message temp(other);
    
            std::swap(size, temp.size);
            std::swap(data, temp.data);
    
            return *this;
        }
    
        Message(Message&& other) noexcept
            : data(std::exchange(other.data, nullptr))
        {
            std::cout << "Message(Message&& other) noexcept\n";
        }
    
        Message& operator=(Message&& other) noexcept
        {
            std::cout << "Message& operator=(Message&& other) noexcept\n";
    
            Message temp(std::move(other));
    
            std::swap(data, temp.data);
            std::swap(size, temp.size);
    
            return *this;
        }
    };
    
    std::queue<Message> message_queue;
    
    int main()
    {
        Message message(50);
    
        message_queue.push(message);
    
        Message other_message = message_queue.front();
        message_queue.pop();
    
        std::cout << (void*) message.data << "\n" << (void*) other_message.data << "\n";
    
        return 0;
    }
    

    我的输出仍然显示数据指向两个不同的位置。

    Message(const Message& other)
    Message(const Message& other)
    0x1b0c2a53400
    0x1b0c2a52f40
    

    我相信我仍然做错了什么,我只是不确定

    1 回复  |  直到 4 月前
        1
  •  6
  •   Remy Lebeau    4 月前

    message_queue.push(std::move(message));

    这将使用您定义的复制构造函数(因为您没有提供移动构造函数)。在那里,您将分配新的内存并将数据复制到其中。所以, other.data this->data 将指向不同的地址。

    Message other_message = message_queue.front();

    这将再次使用复制构造函数,再次分配新内存并将数据复制到其中。新对象的 data 将指向第三个地址。

    您现在有三种不同的内存分配,如果不这样做,所有内存都会泄漏 delete[] 记忆在 ~Message() .

    有没有一种方法可以通过队列和带有字符数组的自定义结构来阻止内存泄漏?

    是的,使用a std::string std::vector<char> 。或者,如果您必须自己管理内存,请阅读 Rule of 3/5/0 并实施这些:

    • 复制和移动构造函数
    • 复制和移动分配运算符
    • 破坏者