我困惑于为什么析构函数会无休止地自我调用,当我尝试通过静态函数调用LeakySingleton
在堆上构造一个对象时说create_instance()
,然后尝试通过[ C0]操作。
据我所知,考虑下面的源代码清单,delete
中的变量leaky_singleton
指向main()
返回的堆分配资源。因此,我们已通过create_instance()
函数在堆上间接分配了一个对象LeakySingleton
。现在,如果我显式调用create_instance
上的delete运算符或delete函数,则它将首先调用析构函数,并检查其是否满足leaky_singleton
条件,然后删除instance != nullptr
指向的对象应为已删除。如果此对象instance
被删除,则dtor没有理由再次调用自身,或者我在这里丢失了什么吗?
使用和不使用valgrind调用都会导致分段错误(由于堆栈溢出而导致无效的内存访问):
LeakySingleton::instance
逐步调试,导致无休止的析构函数调用(堆栈溢出的元凶)。>>
从cplusplus.com(Segmentation fault (core dumped)
):
如果删除对象,它将尝试删除自身,这将使它尝试删除自身,这将导致它删除本身,这将...
为什么当我简单地使用http://www.cplusplus.com/forum/general/40044/运算符/函数来释放静态类成员变量
delete
指向的堆对象LeakySingleton
时,为什么试图删除自身?堆分配的资源由指向LeakySingleton::instance
对象的LeakySingleton::instance
指针变量指向。那么,为什么显式LeakySingleton
函数调用不删除或取消分配已分配的堆对象,而是无限递归?我在这里想念什么?
(我目前对dtor和ctor的理解:delete
函数/操作符为堆上的对象分配内存并调用构造函数,new
函数调用析构函数,在我的情况下还调用delete
运算符/函数内部。)
来源:
main.cpp
::delete
Makefile
class Singleton final
{
public:
static Singleton & create_instance(int);
~Singleton() = default;
private:
int x;
Singleton(int);
Singleton(Singleton &) = delete;
Singleton(Singleton &&) = delete;
Singleton & operator=(Singleton &) = delete;
Singleton & operator=(Singleton &&) = delete;
};
Singleton::Singleton(int t_x) : x{t_x}
{}
Singleton & Singleton::create_instance(int t_x)
{
static Singleton instance{t_x};
return instance;
}
// Potential endless dtor calls inside:
class LeakySingleton final
{
public:
static LeakySingleton * create_instance(int);
~LeakySingleton();
private:
int x;
static LeakySingleton * instance;
LeakySingleton(int);
LeakySingleton(LeakySingleton &) = delete;
LeakySingleton(LeakySingleton &&) = delete;
LeakySingleton & operator=(LeakySingleton &) = delete;
LeakySingleton & operator=(LeakySingleton &&) = delete;
};
LeakySingleton * LeakySingleton::instance = nullptr;
LeakySingleton::LeakySingleton(int t_x) : x{t_x}
{}
LeakySingleton::~LeakySingleton()
{
if (instance != nullptr)
{
delete instance;
instance = nullptr;
}
}
LeakySingleton * LeakySingleton::create_instance(int t_x)
{
if (instance == nullptr)
{
instance = new LeakySingleton{t_x};
}
return instance;
}
int main()
{
// The correct implementation with no issues:
{
Singleton & singleton = Singleton::create_instance(42);
}
// The faulty implementation causing the dtor to recurse endlessly and resulting in a segfault:
{
LeakySingleton * leaky_singleton = LeakySingleton::create_instance(42);
delete leaky_singleton;
}
return 0;
}
我对为什么析构函数调用自己无休止的次数感到困惑,当我尝试通过静态函数调用create_instance()然后在堆上构造对象时说LeakySingleton,然后...
您有一个令人讨厌的循环,在CC = g++
CFLAGS = -g -Wall -Wextra -pedantic -std=c++11
SRC = main.cpp
TARGET = app
RM = rm -rf
.PHONY: all clean
all: $(TARGET)
clean:
$(RM) $(TARGET)
$(TARGET): $(SRC)
$(CC) $(CFLAGS) $^ -o $@
中,您有:
在C ++中,instance = nullptr;
将调用类析构函数。
在析构函数中删除实例,启动析构函数调用。
首先,由于class LeakySingleton final {
public:
static LeakySingleton& create_instance(int);
static void destroy_instance();
~LeakySinglton() = default;
private:
static LeakySingleton *instance;
...
};
void LeakySingleton::destroy_instance() {
if (instance != nullptr) {
delete instance;
instance = nullptr;
}
}
不能直接创建,也不能直接销毁: