Home > other >  Variable not set inside __attribute__((constructor)) or global static variable reset after __attribu
Variable not set inside __attribute__((constructor)) or global static variable reset after __attribu

Time:11-29

I have a std::vector which need to filled with some random values when library is loaded. but I see it is been reset after library is loaded. Is it because of global and static

Library code:

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;
}

Main code:

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

Output:

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

In the above output I expect 20 in cout main function but I receive empty vector

CodePudding user response:

You are most likely suffering from a static initialization order fiasco.

I suggest lazy initialization of the vector:

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

Then in your shared library constructor:

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

And also in the function making a copy:

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

CodePudding user response:

Another option is to control the order of the vector initialization and constructor call with priorities:

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

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

Live demo: https://godbolt.org/z/bh9zj9cE3

Possibly OT to the problem: Note that using I/O (as std::cout in your case) in a constructor can suffer from the very same problem. See, e.g., gcc linker extension __attribute__((constructor)) causes crash in main().

  • Related