gpt4 book ai didi

c++ - 我不明白如何解决内存泄漏 C++ 的问题

转载 作者:行者123 更新时间:2023-12-01 15:10:18 25 4
gpt4 key购买 nike

健康)状况
在讲座中,我们已经开始实现我们的 vector 。在此任务中,您需要开发它:添加 Size , Capacity , 和 PushBack方法。发送 simple_vector.h包含 SimpleVector 的头文件用于验证的类模板声明和定义:
要求:

  • Capacity方法应该返回 vector 的当前容量——适合 vector
  • 当前分配的内存块的元素数量。
  • Size方法必须返回 vector 中的元素个数
  • PushBack方法在 vector 的末尾添加一个新元素;如果当前分配的内存块中没有剩余空间(即 Size() == Capacity() ),则 vector 必须分配大小为 2 * Capacity() 的 block ,将所有元素复制到其中,并删除旧元素。
  • 第一次调用PushBack新创建对象的方法必须使容量等于 1
  • Push Back方法必须具有摊销常数复杂度
  • beginend方法必须返回迭代器当前 vector 的开始和结束
    vector 分配的当前内存块必须在析构函数中释放
  • 另请参阅随附的解决方案模板,了解使用 SimpleVector 的其他要求在单元测试中。

  • 准备决定:
  • simple_vector.h : https://d3c33hcgiwev3.cloudfront.net/q-OL4qX_EeilzRLZf2WxfA_ac4e8270a5ff11e89fd0455a8819d387_simple_vector.h?Expires=1596067200&Signature=cLfBpytTripoqpOYaW9g4~2-JqTI~8HtxahNwNATwBeq28RdXCvkcqghN~UUPv~wx1XZTVOTs8JDsZQjEALk6Soy70QFADkK9lSfFpLNcQq-Dxd4oxk-C5QDEhadM1LrVGe8Rmz0jRYgIV5sDTvAATBhiY3k-KqbAaDe1AK6QiE_&Key-Pair-Id=APKAJLTNE6QMUY6HBC5A
  • simple_vector.cpp : https://d3c33hcgiwev3.cloudfront.net/uoPvEoauEeianAr0yIdmDg_bae6cec086ae11e88d9327752d64e780_simple_vector.cpp?Expires=1596067200&Signature=CE1Mox1yU6LjGDXL1xstxT9anv9NI~otNwhBw5AbPyLBquRIi9E6cotR~BQsrvU-djoksfjV9YgnsyF00eFnVjsk~oF0z18wkVkgdIirPB-NNLH0aFvD4WFG97qmSuD0WjeetWyi6UR5BKYCnwfO~ax6-HZLM-GWheO9LHc~BvE_&Key-Pair-Id=APKAJLTNE6QMUY6HBC5A

  • 评论 :
    您发送用于验证的头文件不应包含 <vector> , <list> , <forward_list> , <deque> , <map>文件。如果您启用了这些文件之一,您将收到编译错误。
    提示 :
    当然,您对 SimpleVector 的实现类模板将有一个作为指针的字段。在默认构造函数中,您需要使用一些东西对其进行初始化。在讲座中,我们只讨论了一种初始化指针的方法——使用 new 运算符。在 C++ 中,有一个特殊的值表示指针不指向任何内容 — nullptr :
    int* p = nullptr;
    string* q = nullptr;
    map<string, vector<int>>* r = nullptr;
    您可以使用 nullptr 在默认构造函数中初始化指针。
    如何发送:
    工作准备就绪后,您可以在“我的工作”选项卡上为任务的每个部分上传文件。
    这是我的 .h Coursera 测试系统响应的解决方案 10 != 8: Memory leak detected .但是我无法弄清楚泄漏的去向。请帮帮我。
    #pragma once
    #include <cstdlib>

    using namespace std;

    template <typename T>
    class SimpleVector {
    public:
    SimpleVector()
    : data(nullptr)
    , end_(data)
    , size_(0) {}

    explicit SimpleVector(size_t size)
    : data(new T[size])
    , end_(data + size)
    , size_(size) {}

    ~SimpleVector() {
    delete[] data;
    }

    T& operator[](size_t index) { return data[index]; }

    T* begin() const { return data; }
    T* end() const { return end_; }

    size_t Capacity() const { return end_ - data; }

    size_t Size() const { return size_; }

    void PushBack(const T& value) {
    if (size_ == Capacity()) {
    if (size_ == 0) {
    delete[] data;
    data = new T[1];
    data[size_] = value;
    ++size_;
    end_ = data + size_;
    }
    else {
    T* local_data = new T[size_];

    for (size_t i = 0; i < size_; ++i) {
    local_data[i] = data[i];
    }

    delete[] data;
    data = new T[2 * Capacity()];

    for (size_t i =0; i < size_; ++i) {
    data[i] = local_data[i];
    }
    delete[] local_data;

    data[size_] = value;
    ++size_;
    end_ = data + size_ * 2;
    }
    }
    else {
    data[size_] = value;
    size_++;
    }
    }
    private:
    T *data;
    T *end_;
    size_t size_;
    };
    谢谢 提前。

    最佳答案

    PushBack 中存在内存泄漏由于缺乏异常安全性。考虑:

    T* local_data = new T[size_];
    // potentially throwing operations here...
    delete[] local_data;
    如果这些操作抛出,那么 delete[] local_data;永远不会被执行。
    避免这种内存泄漏的典型方法是使用智能指针而不是裸指针来获取所有权。过时的方法是使用 try-catch。

    您的类也未能强制执行 data 的唯一性类不变量。指针。这样的约束对于析构函数的正确性是必不可少的,因为分配必须只删除一次,不能再删除。
    复制类的实例将导致未定义的行为,因为在多个析构函数中删除了相同的指针。另一个后果是赋值运算符会泄漏之前分配的内存(在 UB 发生在析构函数中之前):
    {
    SimpleVector vec(42);
    SimpleVector another(1337);
    SimpleVector vec = another; // memory leak in assignment operator
    } // undefined behaviour in the destructor
    问题出在复制和移动构造函数和赋值运算符中,您已将其保留为隐式生成。隐式生成的特殊成员函数将复制指针值,违反其唯一性(并且在赋值的情况下无法删除先前的分配)。换句话说,这些函数执行浅拷贝。
    使用智能指针作为成员是一个简单的解决方案。否则,您必须实现不会泄漏或违反唯一性的复制和移动构造函数和赋值运算符。
    请注意,即使您确实使用了智能指针,您仍然需要用户定义的拷贝等,因为 end指针。如果您改为使用与 data 相关的整数,那么您可以避免定义这些函数。

    附言无需分配两次,复制两次。相反,分配一个更大的缓冲区,复制旧的,删除旧的,指向新的。

    附言作为旁注:您正在实现的 vector 与标准 vector 的行为完全不同,这可能是您的老师故意的。当我将一个对象添加到包含 10 个元素的 vector 时,我希望只创建一个元素,并且可能由于重定位而复制了 10 个元素,而不是创建了 20 个对象,其中 9 个无法访问。
    vector 的正确实现将内存分配和对象创建分离到该内存中,这允许内存的几何增长而不创建对象,直到它们被添加到 vector 中。我怀疑如何做到这一点超出了你的练习范围。

    关于c++ - 我不明白如何解决内存泄漏 C++ 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63134899/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com