析构函数称为两次,而没有副本构造函数或赋值运算符被称为

问题描述

|| 我有一堂课:
class A
{
public:
    A()
    {
        std::cout << \"Constructor called\" << std::endl;
    }

    ~A()
    {
        std::cout << \"Destructor called\" << std::endl;
    }

    A(const A& another)
    {
        std::cout << \"Copy constructor called\" << std::endl;
    }

    A& operator=(const A& another)
    {
        std::cout << \"Assignment operator= called\" << std::endl;
    }
};
在我非常复杂的项目中,启动应用程序后,得到以下输出:
Constructor called
但是当我按Ctrl + C终止我的应用程序时:
Destructor called
Destructor called
在整个过程中,没有调用复制构造函数或赋值运算符。 我的类
A
具有动态内存分配,因此我必须在析构函数中释放它,但是析构函数以某种方式被调用了两次,这非常糟糕。 我不知道什么可能导致此问题。 我用谷歌搜索了很多。关于“两次调用析构函数”的很多问题是由于复制构造函数(赋值运算符)的隐式调用。 谢谢。 彼得     

解决方法

        如果您以某种方式两次调用了析构函数,则可能有两个对象认为它们通过指针拥有了它。 如果确实有两个认为自己拥有该对象的对象,请考虑使用引用计数的指针,例如Boost :: shared_ptr或tr1 :: shared_ptr来包含它。这样,您不必担心谁最终会调用析构函数。 除了调试器之外,您还可以尝试Valgrind(memcheck)查找程序在何处删除已释放的对象。在这种情况下,它可能不会提供比调试器更多的详细信息,但您应该早晚学习使用Valgrind(memcheck)。 另一种偏执策略是确保在删除内部指针后将其设置为NULL。     ,        很可能您有一个没有显示的构造函数,或者您多次或通过显式或通过
delete
调用析构函数。 在这种情况下,调试器或附加的
cout
会比我们更有用。     ,        在析构函数中放置一个断点。然后,无论何时调用它,您都可以获取堆栈跟踪并查看从何处调用它。 编辑: 您可以期望复制省略号对此类琐碎的调试语句造成严重破坏。     ,        就我而言,我没有使用任何指针,但是析构函数仍然被调用两次。我要解决的问题是重写副本分配运算符
MyClass& operator=(const MyClass& other)
。不太确定为什么自动生成的运算符会引起问题,但看起来确实会引起问题。     

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...