C++ 中单例类中的内存泄漏

Memory leak in singleton class in c++

本文关键字:泄漏 内存 单例类 C++      更新时间:2023-10-16

我有一个单例类。我正在创建它的一个对象。使用它。一旦它超出范围,将调用析构函数。

再次创建一个新对象,因为 instanceFlag 为 false,它将再次分配新内存。

#include <iostream>
using namespace std;
class Singleton
{
private:
    static bool instanceFlag;
    static Singleton *single;
    Singleton()
    {
        //private constructor
    }
public:
    static Singleton* getInstance()
    {
        if(! instanceFlag)
        {
            single = new Singleton();
            instanceFlag = true;
            return single;
        }
        else
        {
            return single;
        }
    }
    void method()
    {
        cout << "Method of the singleton class" << endl;
    }
    ~Singleton()
    {
        instanceFlag = false;
    }
};
bool Singleton::instanceFlag = false;
Singleton* Singleton::single = NULL;

int main()
{
    Singleton *sc1,*sc2;
    {
        sc1 = Singleton::getInstance();
        sc1->method();
        delete sc1;
    }
    sc2 = Singleton::getInstance();
    sc2->method();
    return 0;
}

我的疑问是旧记忆会怎样?我认为这是内存泄漏。如果是,如何在给定的代码中解决此问题?

任何评论都将有助于理解内部结构。

指针

是包含内存中某物地址的变量。与任何其他变量一样,指针可以超出范围,但这与它所指向的信息无关。这就是泄漏发生的方式。

{
    char* p = new char[128];
}

p超出范围时,分配的地址会消失,但分配不会受到影响;它仍然被分配并且其内容不受影响,就像扔掉信封会影响它所针对的房子一样。

要解决这个问题,您需要一些带有引用计数的东西,例如 std::shared_ptr/std::weak_ptr 或 RAII 容器,例如 std::unique_ptr 等。

最好使用引用实现单例模式。

class Singleton {
    Singleton() {
        // constructor code...
    }
    static Singleton s_singleton;
public:
    static Singleton& GetSingleton() {
        return s_singleton;
    }
};

class Singleton {
    Singleton() = delete; // if you don't have a ctor, lets not have one at all.
public:
    static Singleton& GetSingleton() {
        static singleton;
        return singleton;
    }
};

我使用易于使用的valgrind,它用于检测内存泄漏。http://valgrind.org/docs/manual/quick-start.html

请参阅头先 c 教程以检测内存泄漏。

sc1sc2是指针,它们不是Singleton对象。当它们超出范围时,没有要求Singleton::~Singleton()

你的问题在别处。删除sc1 时,不会将Singleton::instanceFlag设置为 false 。这意味着sc2->method()取消引用指向已删除对象的指针。

您应该改为将析构函数设为私有,并引入一个新的成员函数来删除对象。另外,您真的不需要Singleton::instanceFlag.只需检查Singleton::single == NULL。删除它时,请再次将其设置为 NULL。

首先,你实现单例模式的方式是错误的,

if(! instanceFlag)
{
    single = new Singleton();
    instanceFlag = true;
    return single;
}
else
{
    return single;
}

使用像上面这样的标志不是一个很好的实现,你没有将标志设置为 true,因此对单例类进行新的分配,这确实违反了单例模式的规则

您可以使用如下所示的内容

====

==================================================================
public:
    static Singleton* getInstance()
    {
        if(! single )//check if class is already instantiated once (allocation already 
          //done)
        {
            single = new Singleton();
            instanceFlag = true;
        }
            return single;
    }

或者您也可以使用非指针

public:
    static Singleton& getInstance()
    {
        static Singleton single
        return single;
    }

不应删除单例。

您的问题已经回答了。