类链表类的析构函数的双重释放错误
Posted
技术标签:
【中文标题】类链表类的析构函数的双重释放错误【英文标题】:Double free error with a destructor of a Linked List-like class 【发布时间】:2021-11-30 10:31:10 【问题描述】:对于学校的一个项目,为了学习 c++,我必须在不同的课程上工作。
其中之一是 Number
类,它是将数字表示为链表:
class Number
public:
Number( unsigned long l )
first_ = new Digit static_cast< DigitType >( l % number_base ), nullptr ;
if ( l >= number_base )
first_->next_ = (Number( l / number_base )).first_;
~Number()
[...]
private:
using DigitType = unsigned int;
static const DigitType number_base 10u ;
struct Digit
DigitType digit_;
Digit * next_;
;
Digit * first_;
;
Number n 123 ;
因此将是 n -> 3 -> 2 -> 1 -> nullptr
我必须编写析构函数,所以我采用了类似于单链表的方法:
~Number()
Digit * current_address = first_;
while (current_address != nullptr)
Digit * next_address = current_address->next_;
delete current_address;
current_address = next_address;
然后我运行这个简单的 sn-p 看看它是否有效:
//Another file
#include <exception>
#include <iomanip>
#include <iostream>
#include <string>
#include <utility>
#include "Number.hpp"
void print_number()
Number n 10 ;
std::cout << n << std::endl;
int main(int argc, char const *argv[])
std::cout << "Starting..." << std::endl;
print_number();
std::cout << "Finished !" << std::endl;
return 0;
./a.out
Starting...
free(): double free detected in tcache 2
Aborted (core dumped)
我想我可能对动态分配有一些误解,因为我觉得我的析构函数不会尝试释放两次相同的地址......知道发生了什么吗?
提前致谢!
【问题讨论】:
first_->next_ = (Number( l / number_base )).first_;
非常有问题,您正在从临时对象分配一个指针(执行此行后将立即调用其析构函数)
【参考方案1】:
问题出在这里:
first_->next_ = (Number( l / number_base )).first_;
这会创建一个临时编号,在创建后将调用其析构函数,释放内存。
一个更好的方法是简单地使用循环而不是递归。
但是,如果您坚持使用递归,那么不要递归调用构造函数,而是调用具有完全相同逻辑的辅助函数。
我会让你来实现这些想法。
【讨论】:
以上是关于类链表类的析构函数的双重释放错误的主要内容,如果未能解决你的问题,请参考以下文章