c++ 为什么工厂成员函数会挂在全局对象的构造函数中?[关闭]

4nkexdtk  于 2023-04-01  发布在  其他
关注(0)|答案(1)|浏览(79)

**已关闭。**此问题需要debugging details。当前不接受答案。

编辑问题以包含desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem。这将有助于其他人回答问题。
19小时前关门了。
Improve this question
首先,我在这里没有一个完整的最小函数示例来定义工厂,因为我不能访问正在使用的动态库的定义。
我现在寻找的是阅读建议,除非我的问题很明显是一个一般性的问题,不需要函数定义的知识来解释。
假设我们有一个工厂模式的变体,根据DLL附带的文档,它允许以下代码按预期编译和操作:

int main(){
   std::cout << "Start" << std::endl;

   Base* ptr = Base::Create();
   ptr->ConcreteMemberDoSomething();

   std::cout << "End" << std::endl;
}

输出:

Start
/-- Concrete Member... Output --/
End

考虑到这一点,为什么这可能编译,但(一贯)导致程序运行时无限期挂起?:

class Init{
public:
   Base* ptr;
   Init(){
      std::cout << "Ctor start" << std::endl;

      ptr = Base::Create();

      std::cout << "Ctor end" << std::endl;
   };
   ~Init(){
      std::cout << "Dtor" << std::endl;
   };
}

Init obj;

int main(){
   std::cout << "Start" << std::endl;

   obj.ptr->ConcreteMemberDoSomething();

   std::cout << "End" << std::endl;
}

输出:

Ctor start

我希望我对main()有更多的调试工作要做,但我不明白为什么Init构造函数冻结了。我担心这与初始化顺序有关,因为我一直在阅读有关静态初始化顺序的问题,但我不知道我可以尝试修复它,因为我无法访问动态库中编译的任何定义。

bz4sfanl

bz4sfanl1#

这是一个可能的static initialization order fiasco的情况。虽然其他类型的问题是可能的,这种推测是完全基于提供的代码片段。一般来说,创建非函数本地静态对象与动态初始化被认为是坏的编程实践,如果它确实是不可避免的(例如std::cout),carefully designed ad-hoc workarounds必须考虑。
解决这个问题的一种方法是Scott Mayer's Singleton。用户代码不能存储任何指向singleton对象的指针或引用,并且总是使用singleton_t::instance()。一些人建议将Mayer的singleton Package 在单态类型中:

struct mono{
    single* const operator ->() const{
        static single ret{/*TODO:init stuff here*/};
        return std::addressof(ret);
    };
};
//...
{
    //In Some code scope:
    mono x;
    use(x->y);
};

在OP的上下文中,假设存在createdestroy对应物,我们可以使用unique_ptr

struct mono{
    auto const operator ->() const{
        static std::unique_ptr
                    <Base,
                    decltype([](Base *const ptr)
                            {Base::Destroy(ptr);})>
               ret {Base::Create();};
        return ret;
    };
};

如果这样的Destroy存在,并且对象根本不应该是delete d,那么可以使用原始指针来代替智能指针。

相关问题