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

修复了双重自由或损坏错误,但为什么会发生这种情况?[副本]

  •  2
  • minecraftplayer1234  · 技术社区  · 7 年前

    我有以下代码:

    src/main.cpp :

    #include <include/array.hpp>
    
    int main() {
        int temp[] = {1, 2, 3, 4, 5};
        sdizo::array<int> a(temp, 5);
        print_array(a);
        return 0;
    }
    

    include/array.hpp

    #pragma once
    #include <string.h>
    #include <iostream>
    
    namespace sdizo {
    
    template <class T>
    class array {
    private:
        T* data;
        int length;
    
    public:
        array();
        array(T* d, int len);
        ~array();
        T* begin();
        T* end();
    };
    template <typename T>
    array<T>::array() {
        data = nullptr;
        length = 0;
    }
    
    template <typename T>
    array<T>::array(T* d, int len) {
        length = len;
        this->data = new T[len];
        memcpy(this->data, d, sizeof(d[0]) * len);
    }
    template <typename T>
    array<T>::~array() {
        delete[] this->data;
    }
    template <typename T>
    T* array<T>::begin() {
        return &data[0];
    }
    template <typename T>
    T* array<T>::end() {
        return &data[length];
    }
    
    template <typename T>
    void print_array(array<T> ar) {
        for (auto x : ar) {
            std::cout << x << " ";
        }
        std::cout << '\n';
    }
    }
    

    编译时使用: g++ src/*.cpp -I./ -std=c++1z -g -o bin/sdizo1

    现在运行它会出现以下错误:

    enter image description here

    我注意到,当我没有打印数组时,就没有出现错误。我考虑过通过引用传递数组,因为现在它会创建一个本地副本,可能错误是由于调用析构函数两次引起的。所以 void print_array(array<T> &ar) 相反 void print_array(array<T> ar) 工作。

    ~array() 在同一个内存位置被调用了两次,或者类似的东西,但是为什么呢。难道C++编译器还不够智能,不能检测出这类事情吗?或者我应该总是通过引用传递,或者有没有一种方法可以通过值传递,而不通过带有定制析构函数的结构接收此类错误?

    1 回复  |  直到 7 年前
        1
  •  5
  •   François Andrieux    7 年前

    看见 rule of three/five/zero . 您有一个具有原始拥有指针的类。默认的复制构造函数和复制赋值运算符不会执行预期的操作,它们只复制指针。两个或多个实例有一个指向同一数据的指针,每个实例都将其删除。

    print_array 引用它的论点是,您不会使用有缺陷的复制构造函数或复制赋值运算符。这不是问题 打印阵列 ,这是 array 必须更正的类。