关键:不要同一个原始地址去初始化多个共享指针
起因:
今天调代码时发现的错误。(源代码情况类似下图)
int main() {
Tensor3f x = Tensor3f(Dim<3>{1, 2, 3});
Tensor3f y = Tensor3f(Dim<4>{1, 2, 3, 4});
std::shared_ptr<Tensor3f> z(&y);
x.set_grad(z);
return 0;
}
运行后报错(错误信息如下图),定位后发现是在main函数体结束后析构过程中出现的问题,输出各析构函数信息后发现原因是y实例被析构了两次,内存重复释放导致报错。
解决方案
将源代码中的y改为指针形式
int main() {
Tensor3f x = Tensor3f(Dim<3>{1, 2, 3});
Tensor3f* y = new Tensor3f(Dim<4>{1, 2, 3, 4}); //写为指针类型
std::shared_ptr<Tensor3f> z(y);
x.set_grad(z);
return 0;
}
错误原因
原先代码中y为实例,z为指向y的shared_ptr,在程序结束后y先被释放并执行析构函数,而z中的引用计数未受到影响,因此在析构shared_ptr z时仍然会再次执行对y实例的析构操作,导致内存重复析构引发异常。y转换为指针类型后不会被程序自动析构,因此z可以正常对y执行析构操作。