Loki::Singleton、Loki::SmartPtr 和 std::vector 奇怪的内存问题

发布于 2024-07-26 03:52:02 字数 1157 浏览 3 评论 0原文

我在 VC Express 2008 下使用 Loki::SingletonLoki::SmartPtrstd::vector 时遇到问题。以下是我的来源。

#include <iostream>
#include <vector>
#include <loki/Singleton.h>
#include <loki/SmartPtr.h>

class Foo {
  public:
    std::vector<Loki::SmartPtr<Foo>> children ;
    void add() {
        Loki::SmartPtr<Foo> f = new Foo ;
        children.push_back(f) ;
    }
    Foo () {
    }
    ~Foo () {
    }
} ;

typedef Loki::SingletonHolder<Foo> SingletonFoo ;

int main ()
{
    std::cout << "Start" << std::endl ;
    SingletonFoo::Instance().add() ;
    std::cout << "End" << std::endl ;
}

编译和链接没有问题,但是程序完成后,弹出错误:

Windows has triggered a breakpoint in test.exe.
This may be due to a corruption of the heap, which indicates a bug in test.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while test.exe has focus.
The output window may have more diagnostic information.

似乎有些内存被删除了两次,我不太确定。 这是 VC 的 bug 还是我怀念用过的 Loki?

提前致谢。

I had encountered a problem while using Loki::Singleton, Loki::SmartPtr, and std::vector under VC express 2008. Following is my source.

#include <iostream>
#include <vector>
#include <loki/Singleton.h>
#include <loki/SmartPtr.h>

class Foo {
  public:
    std::vector<Loki::SmartPtr<Foo>> children ;
    void add() {
        Loki::SmartPtr<Foo> f = new Foo ;
        children.push_back(f) ;
    }
    Foo () {
    }
    ~Foo () {
    }
} ;

typedef Loki::SingletonHolder<Foo> SingletonFoo ;

int main ()
{
    std::cout << "Start" << std::endl ;
    SingletonFoo::Instance().add() ;
    std::cout << "End" << std::endl ;
}

Compiling and linking has no problem, but after the program finished, an error pops:

Windows has triggered a breakpoint in test.exe.
This may be due to a corruption of the heap, which indicates a bug in test.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while test.exe has focus.
The output window may have more diagnostic information.

It seems some memory are deleted twice, I am quite not sure. Is that a bug of VC or I miss used Loki?

Thanks in advance.

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

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

发布评论

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

评论(3

妞丶爷亲个 2024-08-02 03:52:03

当您使用 VC 时,您应该能够在调试模式下运行代码,一步一步(F10、F11)查看代码在哪里中断。

无论如何,查看 Loki 单例代码,似乎错误来自SingletonHolder::DestroySingleton() 中的断言:

 SingletonHolder<T, CreationPolicy, L, M, X>::DestroySingleton()
00837     {
00838         assert(!destroyed_); // there, but it's a wild guess
00839         CreationPolicy<T>::Destroy(pInstance_);
00840         pInstance_ = 0;
00841         destroyed_ = true;
00842     }

该函数似乎由 LifetimePolicy(此处为 DefaultLifetime)调用,如以下代码所示:

00800     template
00801     <
00802         class T,
00803         template <class> class CreationPolicy,
00804         template <class> class LifetimePolicy,
00805         template <class, class> class ThreadingModel,
00806         class MutexPolicy
00807     >
00808     void SingletonHolder<T, CreationPolicy, 
00809         LifetimePolicy, ThreadingModel, MutexPolicy>::MakeInstance()
00810     {
00811         typename ThreadingModel<SingletonHolder,MutexPolicy>::Lock guard;
00812         (void)guard;
00813         
00814         if (!pInstance_)
00815         {
00816             if (destroyed_)
00817             {
00818                 destroyed_ = false;
00819                 LifetimePolicy<T>::OnDeadReference();
00820             }
00821             pInstance_ = CreationPolicy<T>::Create();
00822             LifetimePolicy<T>::ScheduleDestruction(pInstance_, // here
00823                 &DestroySingleton);
00824         }
00825     }

我不确定为什么它被调用两次,但我猜指向单例的指针首先被销毁(指针,而不是实例)在 SingletonHolder 实例销毁上,然后 LifetimePolicy 尝试调用它的 DestroySingleton() 函数......

但我可能是错的,你必须检查这一点。

As you're using VC, you should be able to run your code in debug mode, step by stp (F10,F11) to see where it breaks.

Anyway, looking at the Loki singleton code, it seems that the error comes from the assert in SingletonHolder::DestroySingleton() :

 SingletonHolder<T, CreationPolicy, L, M, X>::DestroySingleton()
00837     {
00838         assert(!destroyed_); // there, but it's a wild guess
00839         CreationPolicy<T>::Destroy(pInstance_);
00840         pInstance_ = 0;
00841         destroyed_ = true;
00842     }

That function seems to be called by the LifetimePolicy (here DefaultLifetime) as this code suggests :

00800     template
00801     <
00802         class T,
00803         template <class> class CreationPolicy,
00804         template <class> class LifetimePolicy,
00805         template <class, class> class ThreadingModel,
00806         class MutexPolicy
00807     >
00808     void SingletonHolder<T, CreationPolicy, 
00809         LifetimePolicy, ThreadingModel, MutexPolicy>::MakeInstance()
00810     {
00811         typename ThreadingModel<SingletonHolder,MutexPolicy>::Lock guard;
00812         (void)guard;
00813         
00814         if (!pInstance_)
00815         {
00816             if (destroyed_)
00817             {
00818                 destroyed_ = false;
00819                 LifetimePolicy<T>::OnDeadReference();
00820             }
00821             pInstance_ = CreationPolicy<T>::Create();
00822             LifetimePolicy<T>::ScheduleDestruction(pInstance_, // here
00823                 &DestroySingleton);
00824         }
00825     }

I'm not sure why it is called twice, but I guess the pointer to the singleton is first destroyed (the pointer, not the instance) on the SingletonHolder instance destruction and then the LifetimePolicy try to call it's DestroySingleton() function...

But I might be wrong, you'll have to check that.

伤感在游骋 2024-08-02 03:52:03

IMR,您不能在 stl 容器中使用某些智能指针,这正是发生的问题。 如果内存有用,则与 stl 容器如何复制不符合智能指针预期使用方式的值有关。

IMR, you can't use certain smart pointers in stl containers, and this is the exact problem that occurs. If memory serves, it has to do with how the stl containers copy the values not conforming to how smart pointers expect to be used.

极致的悲 2024-08-02 03:52:03

Loki的智能指针对于STL容器没有任何问题。 如果您以这种方式重写此示例:

#include <iostream>
#include <vector>
#include <loki/Singleton.h>
#include <loki/SmartPtr.h>

class Foo {
  public:
    std::vector<Loki::SmartPtr<Foo>> children ;
    void add() {
        Loki::SmartPtr<Foo> f = new Foo ;
        children.push_back(f) ;
    }
    Foo () {
    }
    ~Foo () {
    }
} ;

// typedef Loki::SingletonHolder<Foo> SingletonFoo ;

int main ()
{
    Loki::SmartPtr<Foo> root = new Foo;
    std::cout << "Start" << std::endl ;
    // SingletonFoo::Instance().add() ;
    root->add();
    std::cout << "End" << std::endl ;
}

它可以正常工作,没有任何问题。

这里发生的情况是,同一个类不应该同时用作 Loki::SingletonLoki::SmartPtr - 它是直接创建和销毁的在 Loki::Singleton 中,但为 Loki::SmartPtr 维护引用计数。

但是如果您使用 Loki::SmartPtr 作为 Loki::Singleton 的参数,它就可以工作! 您必须对代码进行的唯一修改是专门化 Loki::CreateUsingNew 类,以创建使用新创建的 Foo 初始化的 Loki::SmartPtr

#include <iostream>
#include <vector>
#include <loki/Singleton.h>
#include <loki/SmartPtr.h>

class Foo {
  public:
    std::vector<Loki::SmartPtr<Foo>> children ;
    void add() {
        Loki::SmartPtr<Foo> f = new Foo ;
        children.push_back(f) ;
    }
    Foo () {
    }
    ~Foo () {
    }
};

namespace Loki {
    template<class T>
    struct CreateUsingNew<class Loki::SmartPtr<T>> {
        static Loki::SmartPtr<T>* Create()
        { return new Loki::SmartPtr<T>(new T); }

        static void Destroy(Loki::SmartPtr<T>* p)
        { delete p; }
    };
}

typedef Loki::SingletonHolder<Loki::SmartPtr<Foo>> SingletonFoo ;

int main ()
{
    std::cout << "Start" << std::endl ;
    SingletonFoo::Instance()->add() ;
    std::cout << "End" << std::endl ;
}

Loki's smart pointers have no problems with STL containers. If you re-write this sample this way:

#include <iostream>
#include <vector>
#include <loki/Singleton.h>
#include <loki/SmartPtr.h>

class Foo {
  public:
    std::vector<Loki::SmartPtr<Foo>> children ;
    void add() {
        Loki::SmartPtr<Foo> f = new Foo ;
        children.push_back(f) ;
    }
    Foo () {
    }
    ~Foo () {
    }
} ;

// typedef Loki::SingletonHolder<Foo> SingletonFoo ;

int main ()
{
    Loki::SmartPtr<Foo> root = new Foo;
    std::cout << "Start" << std::endl ;
    // SingletonFoo::Instance().add() ;
    root->add();
    std::cout << "End" << std::endl ;
}

it works without any problems.

What is happening here, is that same class isn't supposed be used as Loki::Singleton and in Loki::SmartPtr at the same time - it's created and destroyed directly in Loki::Singleton, but reference count is maintained for Loki::SmartPtr.

But if you use Loki::SmartPtr<Foo> as parameter of Loki::Singleton it works! The only modification you have to make to your code is a specialization of Loki::CreateUsingNew class to create Loki::SmartPtr<Foo> initialized with freshly created Foo:

#include <iostream>
#include <vector>
#include <loki/Singleton.h>
#include <loki/SmartPtr.h>

class Foo {
  public:
    std::vector<Loki::SmartPtr<Foo>> children ;
    void add() {
        Loki::SmartPtr<Foo> f = new Foo ;
        children.push_back(f) ;
    }
    Foo () {
    }
    ~Foo () {
    }
};

namespace Loki {
    template<class T>
    struct CreateUsingNew<class Loki::SmartPtr<T>> {
        static Loki::SmartPtr<T>* Create()
        { return new Loki::SmartPtr<T>(new T); }

        static void Destroy(Loki::SmartPtr<T>* p)
        { delete p; }
    };
}

typedef Loki::SingletonHolder<Loki::SmartPtr<Foo>> SingletonFoo ;

int main ()
{
    std::cout << "Start" << std::endl ;
    SingletonFoo::Instance()->add() ;
    std::cout << "End" << std::endl ;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文