Warnung C26426

Der globale Initialisierer ruft eine Nicht-Constexpr-Funktion "Symbol" auf (i.22)

C++ Core Guidelines

I.22: Vermeiden einer komplexen Initialisierung globaler Objekte

Die Reihenfolge der Ausführung von Initialisierern für globale Objekte kann inkonsistent oder nicht definiert sein, was zu Problemen führen kann, die schwer zu reproduzieren und zu untersuchen sind. Um solche Probleme zu vermeiden, sollten globale Initialisierer nicht von externem Code abhängen, der zur Laufzeit ausgeführt wird, und das kann von Daten abhängen, die noch nicht initialisiert sind. Diese Regel kennzeichnet Fälle, in denen globale Objekte Funktionen aufrufen, um ihre Anfangswerte abzurufen.

Hinweise

  • Die Regel ignoriert Aufrufe von constexpr Funktionen oder systeminternen Funktionen, wenn davon ausgegangen wird, dass diese Aufrufe zur Kompilierungszeit berechnet werden oder die vorhersehbare Ausführung zur Laufzeit garantieren.

  • Aufrufe an Inlinefunktionen werden weiterhin gekennzeichnet, da die Überprüfung nicht versucht, ihre Implementierung zu analysieren.

  • Diese Regel kann in vielen gängigen Szenarien laut sein, in denen eine Variable eines benutzerdefinierten Typs (oder eines Standardcontainers) global initialisiert wird. Dies ist häufig auf Aufrufe von Konstruktoren und Destruktoren zurückzuführen. Es ist immer noch eine gültige Warnung, da sie auf Orte zeigt, an denen unvorhersehbares Verhalten vorhanden sein kann oder wenn zukünftige Änderungen im externen Code zu Instabilität führen können.

  • Statische Klassenmber werden als global betrachtet, sodass ihre Initialisierer ebenfalls überprüft werden.

Codeanalysename: NO_GLOBAL_INIT_CALLS

Beispiele

Überprüfung der externen Version:

// 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

Die überprüfung der externen Version hat zuverlässiger gemacht:

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