修复了双重释放或损坏错误,但为什么会发生?
Fixed double free or corruption error, but why does it occur?
我有以下代码:
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++ 编译器不够智能,无法检测到这些事情吗?或者我应该始终通过引用传递,还是有一种方法可以通过值传递并且不会收到带有自定义析构函数的结构的此类错误?
我知道对于许多比我聪明的人来说这可能会很无聊,但是嘿,他没有质疑,没有学习。
参见rule of three/five/zero。您有一个带有原始拥有指针的 class。您的默认复制构造函数和复制赋值运算符不会执行您可能期望的操作,它们只会复制指针。两个或多个实例具有指向相同数据的指针,并且每个都将其删除。
编辑:澄清一下,当您更改 print_array
以通过引用获取它的参数时没有发现问题的原因是您不会使用有缺陷的复制构造函数或复制赋值运算符。这不是 print_array
的问题,而是 array
class 中的缺陷,必须更正。
我有以下代码:
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++ 编译器不够智能,无法检测到这些事情吗?或者我应该始终通过引用传递,还是有一种方法可以通过值传递并且不会收到带有自定义析构函数的结构的此类错误?
我知道对于许多比我聪明的人来说这可能会很无聊,但是嘿,他没有质疑,没有学习。
参见rule of three/five/zero。您有一个带有原始拥有指针的 class。您的默认复制构造函数和复制赋值运算符不会执行您可能期望的操作,它们只会复制指针。两个或多个实例具有指向相同数据的指针,并且每个都将其删除。
编辑:澄清一下,当您更改 print_array
以通过引用获取它的参数时没有发现问题的原因是您不会使用有缺陷的复制构造函数或复制赋值运算符。这不是 print_array
的问题,而是 array
class 中的缺陷,必须更正。