Исправлена ошибка double free или corruption, но почему это происходит? [дубликат]
На этот вопрос уже есть ответ здесь:
- Что такое правило трех? 8 ответов
У меня есть следующий код:
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
Теперь запуск его дает следующую ошибку:
Я заметил, что когда я не печатал массив, то никаких ошибок не произошло. Я подумал о передаче массива по ссылке, потому что теперь он создаст локальную копию, и, возможно, ошибка была вызвана вызовом деструктора дважды. Так что void print_array(array<T> &ar)
вместо void print_array(array<T> ar)
сработало.
~array()
был вызван дважды или что-то в этом роде, в одном и том же месте памяти, но почему. Разве компилятор C++ недостаточно умен, чтобы обнаружить такие вещи? Или я должен всегда проходить по ссылке, или есть способ пройти мимо значения и не получить такого рода ошибки со структурой с заказным деструктором?
Я знаю, что это, вероятно, будет скучно для многих ppl умнее меня, но эй, тот, кто ничего не спрашивает, ничего не узнает.1 ответ:
СмотритеПравило трех/пяти/нуля . У вас есть класс с необработанным указателем владельца. Конструктор копирования по умолчанию и оператор присваивания копирования не будут делать то, что вы ожидаете, они только копируют указатель. Два или более экземпляра имеют указатель на одни и те же данные, и каждый удаляет его.
Edit: чтобы пояснить, причина, по которой вы не замечаете проблему, когда вы изменяете
print_array
, чтобы взять его аргумент по ссылке, заключается в том, что вы не будете использовать дефектный конструктор копирования или назначение копирования оператор. Это не проблема сprint_array
, это дефект в классеarray
, который должен быть исправлен.