Schwarz计数器为传染媒介

时间:2013-08-12 17:48:48

标签: c++ c++11

我正在研究一个案例,我将有一个全局静态std :: vector,我需要保证在各种翻译单元中的某些静态对象之前进行初始化(构造)。

当我查看如何处理这个问题时,我遇到了两个建议的解决方案:

  1. 在全局函数中使用静态对象代替全局静态对象。
  2. Schwarz Counters
  3. 我对使用Schwarz计数器的担心是std :: vector将被初始化两次。从this链接我得到“一种有用的技术,用于确保全局对象仅在初次使用时初始化一次,以保持使用它的翻译单元数量。”

    全局只被初始化一次是如何工作的?根据我的推理,它将被初始化两次。一旦进入静态初始化的正常过程,一次初始化Schwarz计数器的第一个实例。

    在相关的说明中,初始化代码在Schwarz计数器构造函数中会是什么样的?我只能想到使用新的展示位置。

3 个答案:

答案 0 :(得分:1)

我只能说我过去如何实现它:我设计 一个特殊的“无操作”构造函数,它什么都不做,并且使用 在Schwartz柜台安置新品。类似的东西:

class ForUseAsStatic
{
public:
    enum MakeCtorNoop { makeCtorNoop };
    ForUseAsStatic();   //  normal ctor, called by Schwartz counter.
    ForUseAsStatic( MakeCtorNoop );
                        //  no-op constructor, used when
                        //  defining the variable.
};

形式上,这不能保证 - 允许编译器 在调用构造函数之前再次将内存设置为0, 但我从来没有听说过编译器。

也可以在课堂上放一些旗帜 本身,由构造函数测试。这只适用于 当然是静态对象(因为它需要零初始化) 为了工作)。

另一种可能的技术(我在一些人看到过这种技术) 库)是为对象声明内存 汇编程序,或者如果编译器有一些方法,则作为字节数组 强迫对齐。数据名称通常不会被破坏,所以这个 通常会工作,即使它是正式未定义的行为。 (对于标准库,当然,库作者可以 在编译器中请求扩展以帮助他们 问题)。

最后:今天,单身成语或类似的东西是 通常倾向于这种解决方法。它确实意味着你 必须写myobj().xxx,而不仅仅是myobj.xxx,但是 这通常不被认为是一个问题。

答案 1 :(得分:1)

我认为静态初始化问题没有正确的答案,行为未定义,解决方案的选择取决于具体情况。这取决于:

  • 您的编译器及其实现
    • 大多数编译器在单个编译单元中提供保证
    • 顺序可以由链接器确定,有时会受到#pragma
    • 的影响
    • 初始化可以在main开始执行之前的任何时刻发生。
    • 是否将使用静态变量以及何时调用析构函数来实现全局函数。
  • 应用程序架构
    • 是否使用.DLL,某些环境减少了对DLL中静态构造/销毁的管理支持,特别是在需求加载时。
    • 应用程序是否是线程化的,这可能会影响调用静态变量的全局函数。

可能最好的建议是通过以另一种方式设计您的系统来避免这种惨败,尽管这可能不实用。听起来你的应用程序不需要考虑一些关于可移植性的问题,而是针对特定编译器的特定环境。

#pragma /编译器选项

您可能没有考虑过的一个选项是,是否有一些编译器支持您需要的内容。

对于Windows,请参阅: http://support.microsoft.com/kb/104248

对于g ++: 启用init-priority并使用__attribute__ ((init_priority (n)))

让Swartz计数器正常工作

一些例子省略的是空间的对象只是为被正确对齐的被分配对象保留。这避免了你提到的一个结构。例如,在g ++ gnu中使用:

typedef char fake_istream[sizeof(istream)] __attribute__ ((aligned(__alignof__(istream))))
...
fake_istream cin;

为对象分配空间。编译单元外部的所有代码都将此区域称为extern istream cin(通过标题),并使用就地新的初始化。应该注意确保漂亮的计数器是线程安全的(原子)。

答案 2 :(得分:0)

你可以使用另一个间接级别:让你的全局变量是一个指向vector的指针(它将被零初始化),并让你的计数器new为向量并将结果存储在指针中。 / p>