类链表类的析构函数的双自由错误



在学校的一个项目中,为了学习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;
}
}

然后运行这个简单的代码片段,看看它是否有效:

//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_;

创建一个临时数,创建后调用它的析构函数,释放内存。

更好的方法是简单地使用循环而不是递归。

然而,如果你坚持递归,然后递归地调用构造函数,调用一个helper函数相同的逻辑。

我将把这些想法交给你来执行。

最新更新