Поделиться через


Предупреждение C26426

Глобальный инициализатор вызывает функцию без контекспра "символ" (i.22)

C++ Core Guidelines

I.22. Избегайте сложной инициализации глобальных объектов

Порядок выполнения инициализаторов для глобальных объектов может быть несогласованным или неопределенным, что может привести к проблемам, которые трудно воспроизвести и исследовать. Чтобы избежать таких проблем, глобальные инициализаторы не должны зависеть от внешнего кода, выполняемого во время выполнения, и которые могут зависеть от данных, которые еще не инициализированы. Это правило помечает случаи, когда глобальные объекты вызывают функции для получения их начальных значений.

Замечания

  • Правило игнорирует вызовы функций или встроенных функций при предположении, что эти вызовы constexpr будут вычисляться во время компиляции или гарантировать прогнозируемую выполнение во время выполнения.

  • Вызовы встроенных функций по-прежнему помечены, так как средство проверки не пытается проанализировать их реализацию.

  • Это правило может быть шумным во многих распространенных сценариях, когда переменная определяемого пользователем типа (или стандартного контейнера) инициализирована глобально. Это часто связано с вызовами конструкторов и деструкторов. Он по-прежнему является допустимым предупреждением, так как он указывает на места, где может существовать непредсказуемое поведение или где будущие изменения во внешнем коде могут привести к нестабильности.

  • Статические члены класса считаются глобальными, поэтому их инициализаторы также проверяются.

Имя анализа кода: NO_GLOBAL_INIT_CALLS

Примеры

Проверка внешней версии:

// api.cpp
int api_version = API_DEFAULT_VERSION; // Assume it can change at run time, hence non-const.
int get_api_version() noexcept {
    return api_version;
}

// client.cpp
int get_api_version() noexcept;
bool is_legacy_mode = get_api_version() <= API_LEGACY_VERSION; // C26426, also stale value

Проверка внешней версии была более надежной:

// api.cpp
int& api_version() noexcept {
    static auto value = API_DEFAULT_VERSION;
    return value;
}
int get_api_version() noexcept {
    return api_version();
}

// client.cpp
int get_api_version() noexcept;
bool is_legacy_mode() noexcept {
    return get_api_version() <= API_LEGACY_VERSION;
}