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的错误还是我错过了使用Loki?

提前致谢。

4

3 回答 3

1

当您使用 VC 时,您应该能够在调试模式下运行您的代码,通过 stp (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() 函数...

但我可能错了,你必须检查一下。

于 2009-07-07T19:40:16.300 回答
1

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

于 2009-07-07T19:55:19.500 回答
0

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 ;
}

它可以正常工作。

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

但是,如果您将Loki::SmartPtr<Foo>其用作参数,Loki::Singleton则可以!您必须对代码进行的唯一修改是使用新创建的初始化的Loki::CreateUsingNew类的特殊化:Loki::SmartPtr<Foo>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 ;
}
于 2021-09-02T07:43:48.580 回答