2

首先,如果我的术语有些不准确或不正确,我深表歉意:这是 C++ 的一个方面,我没有过多地处理。

我正在为 iOS 项目使用 Google 的 sparsehash 哈希表实现(我正在处理共享库,因为它针对越狱设备):特别是,我正在使用dense_hash_map:我需要该模板的对象(命名正确吗?)作为在项目中的多个文件之间共享的结构的成员。

我需要在一个函数内访问那个“对象”(即结构内的dense_hash_map)__attribute__((constructor)),一个共享库的构造函数。问题显然是,模板的“自动构造函数”在 dyld 处理共享库的构造函数之后被调用:只有在函数内部dense_hash_map手动调用构造函数时,我才能使用该对象。mymap = dense_hash_map<const char*, int, hash<const char*>, eqstr>();__attribute__((constructor))

但是,模板构造函数以这种方式被调用了两次,一次是手动调用,一次是根据 C++ 自动构造函数调用。如何在不改变模板本身设计的情况下避免这种情况?

其他奇怪的事情是:

  • 如果该dense_hash_map对象在该函数内被声明为局部变量,则一切正常。
  • 该问题仅发生在共享库中:简单的独立程序不受此问题的影响。

所以,最后,我想问的是:

  1. 如何声明一个模板对象并强制它手动初始化,基本上没有模板构造函数被自动调用?
  2. 模板构造函数在局部/全局变量情况下的处理方式有何不同?

如果我没有使用正确的术语,请告诉我。我希望有人可以阐明这一点,在此先感谢!

更新:不同情况的示例代码。

// global dense_hash_map
dense_hash_map<const char*, int, hash<const char*>, eqstr> months;

__attribute__((constructor)) static void my_constructor_0()
{
    /*
     actually crashes because you need to call set_empty_key()
     right after the template constructor, which has not been called
     yet, at this point
     */
    months.set_empty_key(NULL);
    months["january"] = 31;
}



__attribute__((constructor)) static void my_constructor_1()
{
    // local dense_hash_map
    dense_hash_map<const char*, int, hash<const char*>, eqstr> months;

    /*
     doesn't crash, works as it should and the map is being initialized
     correctly
     */

    months.set_empty_key(NULL);
    months["january"] = 31;
}


// global dense_hash_map
dense_hash_map<const char*, int, hash<const char*>, eqstr> months;

__attribute__((constructor)) static void my_constructor_2()
{
    /*
     works as it should but if you add a log to the template constructor,
     you see it being initialized twice: the first one is the manual call
     and the second one is the automatic constructor
     */

    months = dense_hash_map<const char*, int, hash<const char*>, eqstr>();
    months.set_empty_key(NULL);
    months["january"] = 31;
}
4

1 回答 1

2

阅读C++:何时(以及如何)调用 C++ 全局静态构造函数?http://www.parashift.com/c++-faq-lite/static-init-order.html

似乎有一种叫做“静态初始化顺序惨败”的东西。初始化的顺序因编译而异,因此不确定变量在使用前何时初始化。

http://www.parashift.com/c++-faq-lite/static-init-order-on-first-use.html的建议是创建一个包含静态变量的函数,以确保在首次使用之前进行初始化。

从那开始,并使用这个问题中的 dense_hash_map,这里有一段代码可以防止这个问题:

typedef dense_hash_map<const char*, int, hash<const char*>, eqstr> hashtable;

//singleton function
hashtable *month_singleton() {
    static hashtable *months = NULL;
    //initialization, happens on first run
    if (months == NULL) {
        months = new hashtable();
        months.set_empty_key(NULL);
    }
    return months;
}

__attribute__((constructor)) static void monthly_constructor()
{
    months_singleton()["january"] = 31;
}
于 2013-11-12T21:10:57.520 回答