Управление порядком конструктора статических объектов - PullRequest
6 голосов
/ 17 марта 2012

Я пишу крошечное ядро ​​на c ++ 11 и имею два экземпляра одного и того же типа, которые должны быть созданы до создания любых других статических объектов.

Код, который я написал, выглядит следующим образом:

// test.hpp
class test {
  // blahblah...
};

// test.cpp
typedef char fake_inst[sizeof(test)] __attribute__((aligned(alignof(test))));

fake_inst inst1;
fake_inst inst2;

// main.cpp
extern test inst1;
extern test inst2;

int kmain() {
    // copy data section

    // initialize bss section

    new (&inst1) test();
    new (&inst2) test();

    // call constructors in .init_array

    // kernel stuffs
}

Он собирается и работает, как и ожидалось, без предупреждающих сообщений, но не с LTO.

Я получаю тонны предупреждающих сообщений с жалобами на соответствие типов, и мне интересно, есть ли обходной путь, так каксмущает меня, чтобы найти другие «настоящие» предупреждения или сообщения об ошибках.

Любое предложение?

Ответы [ 4 ]

2 голосов
/ 17 марта 2012

C ++ не предлагает вам способов управления порядком инициализации глобальных объектов в нескольких файлах.Если вам нужно жестко управлять порядком инициализации этих объектов, то я настоятельно рекомендую вам , а не делать их глобальными объектами.Сделайте их глобальными функциями, которые содержат статические объекты и возвращают на них указатели.

Но даже в этом случае это менее опасно, чем полная ручная инициализация.Просто сделайте несколько указателей на эти объекты доступными для тех, кто в них нуждается (желательно не в глобальном масштабе), и все будет в порядке.

1 голос
/ 17 марта 2012

Не могли бы вы использовать init_priority атрибут GCC?

Some_Class  A  __attribute__ ((init_priority (2000)));
Some_Class  B  __attribute__ ((init_priority (543)));

http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html#C_002b_002b-Attributes

0 голосов
/ 17 марта 2012

Возможно, вот так?

// ... .h
template<typename T>
union FakeUnion {
  FakeUnion() {}
  ~FakeUnion() {}

  T inst;
};

extern FakeUnion<test> inst1_;
extern FakeUnion<test> inst2_;
static constexpr test& inst1 = inst1_.inst;
static constexpr test& inst2 = inst2_.inst;
// ... .h end

// ... .cpp
FakeUnion<test> inst1_;
FakeUnion<test> inst2_;
// ... .cpp end

В пределах main вы можете сказать new (&inst1) test;.Теперь он не должен предупреждать о нарушениях несоответствия типов, поскольку в отличие от вашего кода этот код не содержит переменных, которые имеют разные типы в разных файлах.

0 голосов
/ 17 марта 2012
// in an .h file

typedef char fake_inst[sizeof(test)] __attribute__((aligned(__alignof__(test))));

extern fake_inst fake_inst1;
extern fake_inst fake_inst2;

inline test& f_inst1() { return *reinterpret_cast<test*>(fake_inst1); }
inline test& f_inst2() { return *reinterpret_cast<test*>(fake_inst2); }

// and for readability

static test& inst1 (f_inst1());
static test& inst2 (f_inst2());

Надеемся, что и inst1, и f_inst1() будут оптимизированы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...