标签: static-initialization

gcc中模板的非延迟静态成员初始化?

gcc是否对静态成员初始化时间有任何保证,特别是关于模板类?

我想知道在多个编译单元实例化类PWrap_T<T>::p_s之前main(),是否可以保证静态成员()将被初始化.在main的开头尝试手动触摸每个编译单元的符号是不切实际的,但我不清楚其他任何东西是否有效.

我已经用bar()不同单位的方法进行了测试,并且总是得到了预期的结果,但是我需要知道什么时候/如果gcc会将地毯拉出来以及它是否可以预防.

此外,在库完成加载之前,是否会初始化DSO中的所有静态成员?

#include <iostream>
#include <deque>

struct P;
inline std::deque<P *> &ps() { static std::deque<P *> d; return d; }
void dump();

struct P {
  P(int id, char const *i) : id_(id), inf_(i) { ps().push_back(this); }
  void doStuff() { std::cout << id_ << " (" << inf_ << ")" << std::endl; }
  int  const        id_;
  char const *const inf_;
};

template <class T>
struct PWrap_T { static P p_s; }; …
Run Code Online (Sandbox Code Playgroud)

c++ gcc instantiation static-initialization

10
推荐指数
1
解决办法
858
查看次数

__attribute __((构造函数))调用命令混淆

这里的答案表明,静态初始化不调用__attribute __((构造函数)),它在声明顺序中调用.

那么,如果在初始化所有数据时不能保证调用它的目的是什么呢?我们也可以在Foo构造函数中使用我们的((构造函数)代码.

我正在寻找的是一种在共享库中拥有一个代码的方法,该代码将在初始化所有静态数据并调用静态构造函数之后执行.我看到人们推荐__attribute __((构造函数))作为DllMain的替代品; 我们可以看到这是错误的,因为某些静态数据可能仍未初始化.

当然在单个文件(编译单元)中我们可以安排静态.但在典型的程序中有很多文件.在初始化共享库中的所有其他静态之后,有没有办法保证一个文件中的((构造函数))肯定会被调用?

如果我将一个带有静态初始化(构造函数,对象等)的文件放到gcc命令行的末尾:

g++ -shared -fPIC source1.o source2.o MyLastInitChance.o
Run Code Online (Sandbox Code Playgroud)

这个文件的静态构造函数是否保证最后被调用?我试验过,当我改变源文件的顺序时,printfs的顺序改变了; 但它是否在某处指定并保证在编译系统/计算机上相同?

例如,引用:

在链接时,gcc驱动程序在所有可重定位文件之前立即放置crtbegin.o,在所有可重定位文件之后立即放置crtend.o.©

根据我的理解,上面的引用暗示传递给链接器的.o文件的顺序定义了静态初始化的顺序.我对么?

另一个有趣的解决方案可能是编写一个GCC插件来调整静态初始化(例如将代码添加到.ctors部分等).但这只是一个可能有人可以扩展的想法.

这里介绍了另一种可能的解决方案.简而言之,可以使用外部构建后工具来重新排序可执行文件(库)中的.ctors条目.但我不是ELF格式的专家; 我想知道这是否可行且容易以这种方式调整.so文件.

我感兴趣的是解决一个特定的问题,或证明它是不可能解决的(至少为什么上面的解决方案不起作用).

c++ linux gcc shared-libraries static-initialization

9
推荐指数
1
解决办法
5309
查看次数

静态指针指向对象初始化线程安全

在C++ 11中,以下是线程安全的:

void someFunc()
{
    static MyObject object;
}
Run Code Online (Sandbox Code Playgroud)

但是关于

void someFunc()
{
    static MyObject *ptr = new MyObject();
}
Run Code Online (Sandbox Code Playgroud)

这是否是线程安全的?

正如@Nawaz在评论中提到的那样,可能MyObject构造函数不是线程安全的,所以让我们将问题分成几部分:

1)如果ctor是线程安全的(它不访问任何共享状态),这是否是static MyObject *ptr = new MyObject();线程安全的?换句话说,是static int *ptr = new int(0);线程安全的吗?

2)如果ctor不是线程安全的,但是只能通过someFunc从不同的线程调用来创建对象,并且构造函数从未在其他任何地方使用过,那么这是否是线程安全的呢?

c++ thread-safety static-initialization c++11

9
推荐指数
1
解决办法
749
查看次数

防止静态初始化命令"fiasco",C++

有一次,我在读一个真棒C++ FAQ(这是真的好!)并阅读主题如何防止静态初始化命令"惨败".因此作者建议将静态变量包装到函数中,从而通过维护变量的创建顺序来防止"惨败".但在我看来,这是一个粗鲁的解决方法.所以我的问题是,是否有任何现代的,更多的模式导向的方法来防止这种"惨败",但将"静态东西"包装成函数???

c++ static word-wrap static-initialization static-order-fiasco

9
推荐指数
2
解决办法
3382
查看次数

可以在静态初始化期间安全地创建线程吗

在某些时候我记得读过在main()的第一行之前无法安全地创建线程,因为编译器会插入特殊代码来使线程工作在静态初始化时运行.因此,如果您有一个在构造时创建线程的全局对象,您的程序可能会崩溃.但是现在我找不到原始文章了,我很好奇这是一个多么强烈的限制 - 标准是否严格如此?大多数编译器都是如此吗?它会在C++ 0x中保持真实吗?符合标准的编译器是否有可能使静态初始化本身成为多线程?(例如,检测到两个全局对象不会相互接触,并在不同的线程上初始化它们以加速程序启动)

编辑:为了澄清,我试图至少了解实现是否真的在这方面有显着差异,或者它是否是伪标准的东西.例如,从技术上讲,该标准允许改组属于不同访问说明符(public/protected/etc.)的成员的布局.但我知道的编译器实际上没有这样做.

c++ multithreading standards-compliance static-initialization c++11

8
推荐指数
1
解决办法
378
查看次数

在静态初始化期间创建和使用向量是否安全?

我有C++代码,它声明了由函数调用初始化的静态生命周期变量.被调用的函数构造一个vector实例并调用其push_back方法.代码是否会冒险通过C++静态初始化命令惨败?如果没有,为什么不呢?

补充资料:

  1. 什么是"静态初始化命令惨败"?

    它在C++ FAQ 10.14中进行了解释

  2. 为什么我认为使用vector会引发惨败?

    vector构造函数可能会使用动态初始化的另一个静态生命周期变量的值.如果是这样,那么vector在我vector在代码中使用之前,没有什么可以确保变量被初始化.初始化result(参见下面的代码)可能会vectorvector完全初始化依赖项之前调用构造函数,从而导致访问未初始化的内存.

  3. 这段代码到底是什么样的?

    struct QueryEngine {
      QueryEngine(const char *query, string *result_ptr)
        : query(query), result_ptr(result_ptr) { }
    
      static void AddQuery(const char *query, string *result_ptr) {
        if (pending == NULL)
          pending = new vector<QueryEngine>;
        pending->push_back(QueryEngine(query, result_ptr));
      }
    
      const char *query;
      string *result_ptr;
    
      static vector<QueryEngine> *pending;
    };
    
    vector<QueryEngine> *QueryEngine::pending = NULL;
    
    void Register(const char *query, string *result_ptr) {
      QueryEngine::AddQuery(query, result_ptr); …
    Run Code Online (Sandbox Code Playgroud)

c++ stdvector static-initialization

8
推荐指数
1
解决办法
718
查看次数

无法从静态初始化代码启动CUDA内核

我有一个类在其构造函数中调用内核,如下所示:

"ScalarField.h"

#include <iostream>

    void ERROR_CHECK(cudaError_t err,const char * msg) {
        if(err!=cudaSuccess) {
            std::cout << msg << " : " << cudaGetErrorString(err) << std::endl;
            std::exit(-1);
        }
    }

    class ScalarField {
    public:
        float* array;
        int dimension;

        ScalarField(int dim): dimension(dim) {
            std::cout << "Scalar Field" << std::endl;
            ERROR_CHECK(cudaMalloc(&array, dim*sizeof(float)),"cudaMalloc");
        }
    };
Run Code Online (Sandbox Code Playgroud)

"classA.h"

#include "ScalarField.h"


static __global__ void KernelSetScalarField(ScalarField v) {
    int index = threadIdx.x + blockIdx.x * blockDim.x;
    if (index < v.dimension) v.array[index] = 0.0f;
}

class A {
public:
    ScalarField v; …
Run Code Online (Sandbox Code Playgroud)

c++ cuda global-variables static-initialization

8
推荐指数
1
解决办法
1556
查看次数

从全局对象的构造函数调用时的std :: atexit排序

cppreference说std::atexit:

这些函数可以与具有静态存储持续时间的对象的销毁同时被调用,并且保持如果在B的注册之前如果A的注册被排序,则在调用之前对B的调用进行排序的保证. A,同样适用于静态对象构造函数和对atexit的调用之间的顺序

我理解这一段意味着,如果std::atexit在静态初始化期间调用,则在静态对象的销毁过程中,在静态对象被破坏之前调用已注册的函数,该静态对象std::atexit在调用注册函数时被最后初始化.我还解释"可以同时调用"意味着调用可以发生在静态对象析构之间,而不是对单词的多线程解释.

我想知道的是,当初始化开始或完成时,对象是否被视为已初始化(在此排序的上下文中).我写了一个简短的测试来测试这个:

#include <cstdlib>
#include <iostream>

struct foo
{
    foo() 
    {
        std::cout << "ctor\n";
        std::atexit([]() { std::cout << "atexit\n"; });
    }
    ~foo()
    {
        std::cout << "dtor\n";
    }
};

foo my_foo;

int main()
{
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我得到的输出是(http://cpp.sh/3bllu):

ctor
dtor
atexit
Run Code Online (Sandbox Code Playgroud)

这使我相信,my_foo在构建完成之前,不会在这种情况下初始化.换句话说,该函数被认为在my_foo初始化之前已经注册,因此注册函数在my_foo销毁之后执行.

我似乎找不到任何可以保证这种行为的东西,我甚至不完全确定我对引用段落的初步解释是正确的.我描述的行为是我可以依赖的,还是实现定义甚至未定义的行为?

c++ atexit initialization-order static-initialization language-lawyer

8
推荐指数
1
解决办法
247
查看次数

在统一的内联初始化中使用不可复制的值初始化static std :: map

我想初始化一个std::map值不可复制的静态.我将调用我的类ValueClass.ValueClass有一个std::unique_ptr私有成员,我甚至通过扩展non_copyable看起来如下所示确保ValueClass不可复制:

class non_copyable {
public:
    non_copyable() = default;
protected:
    virtual ~non_copyable() = default;
private:
    non_copyable(const non_copyable&) = delete;
    non_copyable& operator=(const non_copyable&) = delete;
};
Run Code Online (Sandbox Code Playgroud)

现在我正在尝试使用我的类作为值来定义std :: map:

static std::map<int, ValueClass> value_classes = {
    {0, ValueClass()},
    {1, ValueClass() }
};
Run Code Online (Sandbox Code Playgroud)

initializer_list尝试复制此类时出现编译错误.

make_map本周末我试图在整个周末编写自己的函数来启用初始化而不复制但是我失败了.我试过这个,其他,但他们没有与Visual Studio编译15.9.4.

如何使用Visual Studio编译器初始化静态std :: map,其中copy不是强制的,并且初始化在一个函数中是统一的?

编辑: 这是现实生活场景的简化版本,我正在尝试使其工作(原谅我缺乏命名约定和案例的不一致):

#include <iostream>
#include <map>

class non_copyable {
public:
    non_copyable() = default;
protected:
    virtual ~non_copyable() …
Run Code Online (Sandbox Code Playgroud)

c++ noncopyable static-initialization c++17

8
推荐指数
2
解决办法
259
查看次数

JVM的静态初始化

语言:Java
版本:12.0.2
字符串源代码如下:

 /* @implNote
 * The actual value for this field is injected by JVM. The static
 * initialization block is used to set the value here to communicate
 * that this static final field is not statically foldable, and to
 * avoid any possible circular dependency during vm initialization.
 */
static final boolean COMPACT_STRINGS;

static {
    COMPACT_STRINGS = true;
}
Run Code Online (Sandbox Code Playgroud)

如何理解这句话:“静态初始化块用于在此处设置值以传达此静态最终字段不可静态折叠,并避免在vm初始化期间出现任何可能的循环依赖性。”

java static-initialization

8
推荐指数
1
解决办法
86
查看次数