C++智能指针在自分配时泄漏?

发布于 2024-08-13 23:29:22 字数 3063 浏览 5 评论 0原文

我在理解为什么我的智能指针类在自我评估时泄漏时遇到了小问题。 如果我这样做,

SmartPtr sp1(new CSine());//CSine is a class that implements IFunction iterface
sp1=sp1;

我的同事就会告诉我,我的智能指针会泄漏。我在智能指针中添加了一些日志消息来跟踪正在发生的情况和测试并报告了这一点:

SmartPtr sp1(new CSine());
->CSine constructor
->RefCounter increment 0->1
->RefCounter constructor
->SmartPtr constructor

sp1=sp1;
->checks if this.RefCounter == to parameter.RefCounter, if true returns the smart pointer unmodified else modifies the object and returns it with the new values; in this case it returns true and returns the object unchanged.

at the end
->SmartPtr destructor
->RefCounter decrement 1->0
->RefCounter destructor
->CSine destructor

我无法理解为什么他们认为我的智能指针泄漏......有什么想法吗? 先感谢您!

class SmartPtr
{
private:
    RefCounter* refCnt;
    void Clear()
    {
        if(!isNull() && refCnt->Decr() == 0)
            delete refCnt;
        refCnt = 0;
    };
public:
    explicit SmartPtr();
    explicit SmartPtr(IFunction *pt):refCnt(new RefCounter(pt)){};
    SmartPtr(SmartPtr& other)
    {
        refCnt = other.refCnt;
        if (!isNull())
            refCnt->Incr();
    };
    virtual ~SmartPtr(void){Clear();};

    SmartPtr& operator=(SmartPtr& other)
    {
        if(other.refCnt != refCnt)
        {
            if(!rVar.isNull())
                other.refCnt->Incr();
            Clear();
            refCnt = other.refCnt;
        }
        return *this;
    };

    SmartPtr& operator=(IFunction* _p)
    {

        if(!isNull())
        {
            Clear();
        }
        refCnt = new RefCounter(fct);
        return *this;
    };

    IFunction* operator->();
    const IFunction* operator->() const;
    IFunction& operator*();
    const IFunction& operator*() const;
    bool isNull() const { return refCnt == 0; };

    inline bool operator==(const int _number) const;
    inline bool operator!=(const int _number) const;
    inline bool operator==(IFunction* _other) const;
    inline bool operator!=(IFunction* _other) const;
    inline bool operator==(SmartPtr& _other) const;
    inline bool operator!=(SmartPtr& _other) const;
};

class RefCounter
{
    friend class SmartPtr;
private:
    IFunction* p;
    unsigned c;

    explicit RefCounter(IFunction* _p):c(0),p(_p)
    {
        if(_p != NULL)
            Incr();
        cout<<"RefCounter constructor."<<endl;
    }
    virtual ~RefCounter(void)
    { 
        cout<<"RefCounter destructor."<<endl;
        if(c == 0)
            delete p; 
    }
    unsigned  Incr()
    {
        ++c;
        cout<<"RefCounter increment count:"<<c-1<<" to "<<c<<endl;
        return c; 
    }
    unsigned  Decr()
    {
        if(c!=0)
        {
            --c;
            cout<<"RefCounter decrement count:"<<c+1<<" to "<<c<<endl;
            return c;
        }
        else
            return 0;
    }
};

i have small problem understanding why my smart pointer class is leaking on self assing.
If i do something like this

SmartPtr sp1(new CSine());//CSine is a class that implements IFunction iterface
sp1=sp1;

my colleagues told me that my smart pointer leaks. I added some log messages in my smart pointer to track what is going on and a test and reported this:

SmartPtr sp1(new CSine());
->CSine constructor
->RefCounter increment 0->1
->RefCounter constructor
->SmartPtr constructor

sp1=sp1;
->checks if this.RefCounter == to parameter.RefCounter, if true returns the smart pointer unmodified else modifies the object and returns it with the new values; in this case it returns true and returns the object unchanged.

at the end
->SmartPtr destructor
->RefCounter decrement 1->0
->RefCounter destructor
->CSine destructor

i can't understand why they consider that my smart pointer leaks...any ideas?
Thank you in advance!

class SmartPtr
{
private:
    RefCounter* refCnt;
    void Clear()
    {
        if(!isNull() && refCnt->Decr() == 0)
            delete refCnt;
        refCnt = 0;
    };
public:
    explicit SmartPtr();
    explicit SmartPtr(IFunction *pt):refCnt(new RefCounter(pt)){};
    SmartPtr(SmartPtr& other)
    {
        refCnt = other.refCnt;
        if (!isNull())
            refCnt->Incr();
    };
    virtual ~SmartPtr(void){Clear();};

    SmartPtr& operator=(SmartPtr& other)
    {
        if(other.refCnt != refCnt)
        {
            if(!rVar.isNull())
                other.refCnt->Incr();
            Clear();
            refCnt = other.refCnt;
        }
        return *this;
    };

    SmartPtr& operator=(IFunction* _p)
    {

        if(!isNull())
        {
            Clear();
        }
        refCnt = new RefCounter(fct);
        return *this;
    };

    IFunction* operator->();
    const IFunction* operator->() const;
    IFunction& operator*();
    const IFunction& operator*() const;
    bool isNull() const { return refCnt == 0; };

    inline bool operator==(const int _number) const;
    inline bool operator!=(const int _number) const;
    inline bool operator==(IFunction* _other) const;
    inline bool operator!=(IFunction* _other) const;
    inline bool operator==(SmartPtr& _other) const;
    inline bool operator!=(SmartPtr& _other) const;
};

class RefCounter
{
    friend class SmartPtr;
private:
    IFunction* p;
    unsigned c;

    explicit RefCounter(IFunction* _p):c(0),p(_p)
    {
        if(_p != NULL)
            Incr();
        cout<<"RefCounter constructor."<<endl;
    }
    virtual ~RefCounter(void)
    { 
        cout<<"RefCounter destructor."<<endl;
        if(c == 0)
            delete p; 
    }
    unsigned  Incr()
    {
        ++c;
        cout<<"RefCounter increment count:"<<c-1<<" to "<<c<<endl;
        return c; 
    }
    unsigned  Decr()
    {
        if(c!=0)
        {
            --c;
            cout<<"RefCounter decrement count:"<<c+1<<" to "<<c<<endl;
            return c;
        }
        else
            return 0;
    }
};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

温馨耳语 2024-08-20 23:29:22
SmartPtr& operator=(SmartPtr& other)
    {
        if(rVar.refCnt != refCnt)

应该是:

    if ( this != & other ) 
SmartPtr& operator=(SmartPtr& other)
    {
        if(rVar.refCnt != refCnt)

should be:

    if ( this != & other ) 
友谊不毕业 2024-08-20 23:29:22

您可能想查看以下引用 在库技术报告中添加通用智能指针的提案

Boost 开发人员发现共享所有权智能指针很难正确实现。其他人也做出了同样的观察。例如,Scott Meyers [Meyers01] 说:

<块引用>

“STL 本身不包含引用计数智能指针,编写一个好的指针(始终正确工作的指针)非常棘手,除非必须这样做,否则您不想这样做。我发布了代码1996 年《更有效的 C++》中的引用计数智能指针,尽管它基于已建立的智能指针实现并提交给经验丰富的开发人员进行广泛的出版前审查,但多年来仍不断出现少量有效的错误报告。引用计数智能指针可能失败的微妙方式数量是惊人的。”

如果这是家庭作业,请阅读如何使用 swap() (成员)函数实现复制构造函数和赋值运算符。否则,不要尝试编写自己的智能指针。 你无法获胜

You might want to look at the following quote from A Proposal to Add General Purpose Smart Pointers to the Library Technical Report:

The Boost developers found a shared-ownership smart pointer exceedingly difficult to implement correctly. Others have made the same observation. For example, Scott Meyers [Meyers01] says:

"The STL itself contains no reference-counting smart pointer, and writing a good one - one that works correctly all the time - is tricky enough that you don't want to do it unless you have to. I published the code for a reference-counting smart pointer in More Effective C++ in 1996, and despite basing it on established smart pointer implementations and submitting it to extensive pre- publication reviewing by experienced developers, a small parade of valid bug reports has trickled in for years. The number of subtle ways in which reference-counting smart pointers can fail is remarkable."

If this is homework, read about how to implement copy ctor and assignment operator using a swap() (member) function. Otherwise, do not try to write your own smart pointer. You cannot win.

无边思念无边月 2024-08-20 23:29:22

我也没有看到泄漏,但我认为还有一些其他问题(除了许多编译器错误 - 这不能是您正在使用的代码):

SmartPtr& operator=(SmartPtr& other)

应该通过 const 引用获取参数。您不必增加 other 的引用计数,因为您可以在非常量左侧执行此操作,因为它们将共享相同的引用计数实例。

接下来,为此类实现分配的规范方法是使用 copy-and-swap idiom - 这意味着您还应该定义一个简单的交换方法(仅交换指针),并且不用担心自分配:)

I don't see a leak either, but I think there are some other problems (other than many compiler errors - this cannot be the code you are using):

SmartPtr& operator=(SmartPtr& other)

should take the argument by const reference. You don't have to increment the reference count of other, because you can do it on the non-const left-hand side, as they will be sharing the same reference count instance.

Next, the canonical way to implement assignment for such classes is using the copy-and-swap idiom - which means you should also define a trivial swap method (which just swaps the pointers), and worry less about self-assignment :)

淡笑忘祈一世凡恋 2024-08-20 23:29:22

我的印象是没有内存泄漏。
可以肯定的是:

  • 使用 valgrind 或 VS 替代方案
  • 使用 std::tr1::shared_ptr 进行测试(如果这不仅仅是教育意义)

My impression is that there is no memory leak.
To be sure:

  • test with valgrind or the VS-alternative
  • use std::tr1::shared_ptr (if this is more than educational)
︶ ̄淡然 2024-08-20 23:29:22

您的代码无法编译,这让我相信您发布的版本不可能是您同事抱怨的版本。

Your code doesn't compile, which leads me to believe that the version you posted can't be the version you colleagues are complaining about.

本宫微胖 2024-08-20 23:29:22

几乎任何智能指针都会有泄漏的情况。如果您使用引用来实现它,这就是必须的方式。还有一百万个其他问题,而且速度很慢。由于它们比原始指针有更多错误,因此如果您从中得到的只是引用计数,那么实际上没有多大用处。我一直想将它们用于一些非常特殊的目的,但它们不适用于一般编程用途。例如,STL 容器中不允许使用它们,这是有原因的。

Pretty much any smart pointer will have cases where it leaks. It's just the way that it has to be if you implement it using references. There's also a million other problems plus they are slow. Since they are buggier than raw pointers there's really not much use if all you get out of it is reference counting. I have been tempted to use them for some very special purposes but they are not for general programming use. There's a reason that they are not allowed in STL containers for example.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文