【问题标题】:How can I call a function or statically initialize an object immediately before main?如何在 main 之前立即调用函数或静态初始化对象?
【发布时间】:2013-02-08 16:36:36
【问题描述】:

简而言之,我希望在尽可能靠近 main()/DllMain() 开头的地方进行特定的静态初始化。这可能是静态初始化期间最后调用的构造函数是可以接受的。

由于这几乎可以肯定是特定于编译器的实现,因此我特别希望使用可视化 C++ 编译器(VS 2010 及更高版本)来实现。将来我可能需要在 GCC 和 Clang 中执行此操作,但这不是当务之急。

长话短说,我在基础库中有一个对象,该对象被静态初始化并在其构造函数中创建一个线程。该线程依赖于我们无法控制的库中的其他静态初始化对象,因此它会导致静态初始化中的竞争条件。如果我可以暂停或避免创建线程,直到所有其他静态初始化完成,这应该可以解决问题(一个简单的 Sleep(5000) 可以避免这个问题,尽管这不是一个可靠的解决方案)。

我可以在 main() 函数中显式调用初始化函数,但这并不理想,因为我们有 20 多个使用该库的二进制文件,因此每个程序员都必须记住在每个二进制文件中运行初始化。如果可能的话,我宁愿把这个责任推给编译器。

【问题讨论】:

  • 第一次使用你的库函数时的延迟初始化怎么样?
  • 现在,这只是我的 2 美分,但我相信如果你想使用一个库,你会很好地初始化它。手动。除此之外,拥有该特定类的全局对象怎么样?这样,它的构造函数将在 main 之前被调用。虽然我再说一遍:在我看来,程序员应该手动初始化它。这样,您就可以 100% 确定订单得到维护。
  • 我不明白为什么你不能简单地在 main 中调用这个函数,因为你将不可避免地不得不触摸所有包含 main 的文件才能将这个“hack”放入..跨度>
  • RefugnicEternium:我同意大多数情况,但是这是一个性能跟踪库,创建可执行文件的程序员可能永远不会直接与之交互(例如,它被他们正在使用的另一个库使用)。已经有一个全局对象,但是由于它启动了一个线程,因此它与第 3 方库 (boost asio) 一起运行到静态初始化顺序竞争条件。 Nim:我正在寻找一种可以完全在库代码中实现的解决方案。 PlasmaHH:没有调用函数来挂钩 init 例程。

标签: c++ visual-c++ main static-initialization


【解决方案1】:

上面Refugnic Eternium的评论是正确的,并提供了一种解决方案。

最好的解决方案是有这样的功能:

BOOL InitMyLib();
MyLib.dll 中的

All 函数和 all 构造函数在调用它之前应该会失败。这样可以确保程序员不会忘记调用它。

【讨论】:

    【解决方案2】:

    创建一个初始化类,然后声明它的静态实例:

    class MyInitializer
    {
        public:
        MyInitializer ()
        {
            doInitStuffHere();
        }
    };
    
    static MyInitializer myInit;
    

    您可以控制何时使用#pragma init_seg 初始化静态变量。例如,#pragma init_seg(lib)。

    Use #pragma init_seg to Control Static Construction (KB104248)

    【讨论】:

    • 我想把它放在 init_seg(user) 中,但是我不明白如何在不诉诸命令的情况下说“在所有其他 init_seg(user) 对象之后最后初始化它”行链接排序。
    猜你喜欢
    • 2011-07-10
    • 2016-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-01
    • 2013-04-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多