【问题标题】:Variable not set inside __attribute__((constructor)) or global static variable reset after __attribute__((constructor)) invoked未在 __attribute__((constructor)) 内设置变量或在调用 __attribute__((constructor)) 后重置全局静态变量
【发布时间】:2022-01-06 05:38:12
【问题描述】:

我有一个std::vector,在加载库时需要填充一些随机值。但我看到它在加载库后被重置。是不是因为globalstatic

库代码:

static std::vector<uint8_t> g_randomNr{};


__attribute__((constructor)) void generateRandomNrAtStart(void)
{
    static bool firstLoad = false;
    g_randomNr.clear();
    if (!firstLoad) {
        firstLoad = true;
        std::cout << "Library is loaded and generating first random number ...\n";
    }

    std::cout << "Generating random number ...\n";


    for (int i = 0; i < 20; i++) {
        g_randomNr.push_back(i);
    }

    std::cout << "Random number generated with length of " << g_randomNr.size() << "\n";
}

void getRandomNr(std::vector<uint8_t>& randomNr)
{
    randomNr = g_randomNr;
}

主要代码:

int main()
{
    std::vector<uint8_t> randomNr{};
    getRandomNr(randomNr);
    
    std::cout << randomNr.size() << "\n";
    return 0;
}

输出:

Library is loaded and generating first random number ...
Generating random number ...
Random number generated with length of 20
0

在上面的输出中,我希望 cout main 函数中有 20 个,但我收到的是空的 vector

【问题讨论】:

  • static std::vector&lt;uint8_t&gt; g_randomNr = makeRandomVector(); 将避免(非标准)属性,全局和该函数之间的顺序问题。

标签: c++ linux c++11 shared-libraries


【解决方案1】:

另一种选择是使用优先级控制向量初始化和构造函数调用的顺序:

__attribute__((init_priority(101))) static std::vector<uint8_t> g_randomNr{};

__attribute__((constructor(102))) void generateRandomNrAtStart() { ... }

现场演示:https://godbolt.org/z/bh9zj9cE3

问题可能是 OT:请注意,在构造函数中使用 I/O(在您的情况下为 std::cout)可能会遇到同样的问题。参见,例如,gcc linker extension __attribute__((constructor)) causes crash in main()

【讨论】:

  • 非常感谢你的回答,我在这背后挣扎了一天
【解决方案2】:

您很可能患有static initialization order fiasco

我建议对vector进行延迟初始化:

auto& instance() {
    static std::vector<uint8_t> g_randomNr;
    return g_randomNr;
}

然后在你的共享库构造函数中:

__attribute__((constructor)) void generateRandomNrAtStart(void)
{
    auto& g_randomNr = instance();
    // ...

还有在制作副本的功能中:

void getRandomNr(std::vector<uint8_t>& randomNr)
{
    randomNr = instance();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-16
    • 1970-01-01
    • 1970-01-01
    • 2012-12-28
    • 2019-06-12
    • 2019-06-25
    • 1970-01-01
    相关资源
    最近更新 更多