静态地图未正确初始化?
static map not intialized correctly?
我在 macOS 应用程序的静态库中使用一些 C++ 代码。 C++ 代码包含以下内容:
static map<char*, char*> aMap1;
__attribute__((constructor))
static void initialize() {
{
static map<char*, char*> aMap2;
printf("map1: %d, map2: %d\n", aMap1.begin() == aMap1.end(), aMap2.begin() == aMap2.end()); // prints map1: 0, map2: 1
}
aMap1.begin()
不等于 aMap1.end()
,即使 aMap1.size()
为 0。sizeof(aMap1)
为 24,并且 &aMap1
处的 24 个字节为 0。在 for 循环之前调用 aMap1.clear()
使 begin()
等于 end()
.
aMap2.begin()
等于 aMap2.end()
,字节数不为零。
我的印象是 aMap1 是自动初始化的,但这似乎不正确?
someFunc
是从 __attribute__((constructor))
函数调用的,因此它是在 aMap1
初始化程序之前调用的。为了解决这个问题,我将代码移到了调度块中。该函数也可以从 main
调用,而不是被标记为构造函数。
static map<char*, char*> aMap1;
__attribute__((constructor))
static void initialize() {
dispatch_async(dispatch_get_main_queue(), ^{
static map<char*, char*> aMap2;
printf("map1: %d, map2: %d\n", aMap1.begin() == aMap1.end(), aMap2.begin() == aMap2.end()); // prints map1: 1, map2: 1
});
}
首先,__attribute__((constructor))
函数是一个实现定义的编译器扩展,因此 C++ 标准无助于理解其行为。
Clang's attribute reference doesn't actually mention it, so we have to go back to GCC's documentation,因为 clang 实现此属性是为了与 C/C++/Objective-C.
的 GNU 方言兼容
The constructor
attribute causes the function to be called automatically before execution enters main ().
到目前为止,与 C++ 静态初始化程序相比,没有指定相对顺序。然而,很快就会发现构造函数运行 before static C++ initialisers:
You may provide an optional integer priority […] A constructor with a smaller priority number runs before a constructor with a larger priority number; […] The priorities for constructor and destructor functions are the same as those specified for namespace-scope C++ objects (see C++ Attributes).
如果您随后查看 documentation for the init_priority()
attribute,您会发现其 priority
参数为:
[…] a constant integral expression currently bounded between 101 and 65535 inclusive. Lower numbers indicate a higher priority.
换句话说,您可以将多个 __attribute__((constructor))
函数以优先级 0…100 的特定相对顺序放置,并以 101…65535 的顺序静态初始化 C++ 对象以覆盖正在初始化的对象的默认行为按照编译单元中的定义顺序,以及跨编译单元未指定的顺序。但这也意味着最后一个构造函数总是在第一个 C++ 静态初始化器之前运行。
这解释了您所看到的行为。您的构造函数在 aMap1
的构造函数之前运行。 aMap1
是自动构造的,但在构造函数完成后才自动构造。
有关解决此问题的方法,请参阅 the relevant entry in the C++ FAQ。
我在 macOS 应用程序的静态库中使用一些 C++ 代码。 C++ 代码包含以下内容:
static map<char*, char*> aMap1;
__attribute__((constructor))
static void initialize() {
{
static map<char*, char*> aMap2;
printf("map1: %d, map2: %d\n", aMap1.begin() == aMap1.end(), aMap2.begin() == aMap2.end()); // prints map1: 0, map2: 1
}
aMap1.begin()
不等于 aMap1.end()
,即使 aMap1.size()
为 0。sizeof(aMap1)
为 24,并且 &aMap1
处的 24 个字节为 0。在 for 循环之前调用 aMap1.clear()
使 begin()
等于 end()
.
aMap2.begin()
等于 aMap2.end()
,字节数不为零。
我的印象是 aMap1 是自动初始化的,但这似乎不正确?
someFunc
是从 __attribute__((constructor))
函数调用的,因此它是在 aMap1
初始化程序之前调用的。为了解决这个问题,我将代码移到了调度块中。该函数也可以从 main
调用,而不是被标记为构造函数。
static map<char*, char*> aMap1;
__attribute__((constructor))
static void initialize() {
dispatch_async(dispatch_get_main_queue(), ^{
static map<char*, char*> aMap2;
printf("map1: %d, map2: %d\n", aMap1.begin() == aMap1.end(), aMap2.begin() == aMap2.end()); // prints map1: 1, map2: 1
});
}
首先,__attribute__((constructor))
函数是一个实现定义的编译器扩展,因此 C++ 标准无助于理解其行为。
Clang's attribute reference doesn't actually mention it, so we have to go back to GCC's documentation,因为 clang 实现此属性是为了与 C/C++/Objective-C.
的 GNU 方言兼容The
constructor
attribute causes the function to be called automatically before execution enters main ().
到目前为止,与 C++ 静态初始化程序相比,没有指定相对顺序。然而,很快就会发现构造函数运行 before static C++ initialisers:
You may provide an optional integer priority […] A constructor with a smaller priority number runs before a constructor with a larger priority number; […] The priorities for constructor and destructor functions are the same as those specified for namespace-scope C++ objects (see C++ Attributes).
如果您随后查看 documentation for the init_priority()
attribute,您会发现其 priority
参数为:
[…] a constant integral expression currently bounded between 101 and 65535 inclusive. Lower numbers indicate a higher priority.
换句话说,您可以将多个 __attribute__((constructor))
函数以优先级 0…100 的特定相对顺序放置,并以 101…65535 的顺序静态初始化 C++ 对象以覆盖正在初始化的对象的默认行为按照编译单元中的定义顺序,以及跨编译单元未指定的顺序。但这也意味着最后一个构造函数总是在第一个 C++ 静态初始化器之前运行。
这解释了您所看到的行为。您的构造函数在 aMap1
的构造函数之前运行。 aMap1
是自动构造的,但在构造函数完成后才自动构造。
有关解决此问题的方法,请参阅 the relevant entry in the C++ FAQ。