Я пытаюсь отладить программу на C ++, скомпилированную с GCC, которая зависает при запуске. Мьютекс GCC защищает статические локальные переменные функции, и кажется, что ожидание получения такой блокировки - вот почему она зависает. Как это происходит, довольно запутанно. Происходит статическая инициализация первого модуля A (есть функции __static_init, которые GCC вызывает, которые видны в обратном следе), которая вызывает функцию Foo (), которая имеет статическую локальную переменную. Статическая локальная переменная - это объект, который конструктор вызывает через несколько слоев функций, затем внезапно обратная трассировка имеет несколько символов, а затем происходит статическая инициализация второго модуля B (функции __static возникают снова и снова) , который затем вызывает Foo (), но так как Foo () никогда не возвращал первый раз, когда мьютекс локальной статической переменной все еще установлен, и он блокируется.
Как один статический инициатор может вызвать другой? Моей первой теорией были разделяемые библиотеки - этот модуль A будет вызывать некоторую функцию в модуле B, которая вызовет загрузку модуля B, вызывая статический init B, но это не так. Модуль A вообще не использует модуль B. Итак, у меня есть второе (и ужасающее) предположение. Скажи это:
Модуль A использует некоторую шаблонную функцию или функцию в шаблонном классе, например, foo<int>::bar()
Модуль B также использует foo<int>::bar()
Модуль A вообще не зависит от модуля B
Во время компоновки у компоновщика есть два экземпляра foo<int>::bar()
, но это нормально, потому что функции шаблона помечены как слабые символы ...
Во время выполнения модуль A вызывает foo<int>::bar
, и запускается статическая инициализация модуля B, даже если модуль B не зависит от модуля A! Зачем? Потому что компоновщик решил использовать экземпляр b модуля foo :: bar вместо экземпляра модуля A во время компоновки.
Допустим ли этот конкретный сценарий? Или статический init одного модуля никогда не должен запускать статический init в другом модуле?
Пояснение: GCC автоматически создает мьютексы для защиты любой статической переменной функции. Я ничего не делаю с мьютексами сам. Это способ, используемый GCC для обеспечения безопасности потоков статических переменных функций.
Обновление : я знаю, что статическая инициализация не определена между единицами перевода и что я не должен зависеть от заказа. Но мне любопытно, если это нормальное поведение как ключ к устранению проблемы. Это нормально для компилятора генерировать код, который делает это, или это потенциально указывает на ошибку в GCC?