Verbesserungen der C++-Konformität, Behavior Changes und Fehlerbehebungen in Visual Studio 2022

Microsoft C/C++ in Visual Studio (MSVC) nimmt bei jedem Release Verbesserungen bei der Konformität mit Standards sowie bei Fehlerbehebungen vor. Dieser Artikel listet die Verbesserungen nach Hauptrelease und dann nach Versionen auf. Um direkt zu den Änderungen für eine bestimmte Version zu gelangen, verwenden Sie die unten stehende Liste In diesem Artikel.

In diesem Dokument werden die Änderungen in Visual Studio 2022 aufgelistet. Informationen zu den Änderungen in Visual Studio 2019 finden Sie unter Verbesserungen der C++-Konformität in Visual Studio 2019. Informationen zu den Änderungen in Visual Studio 2017 finden Sie unter Verbesserungen der C++-Konformität in Visual Studio 2017. Eine vollständige Liste der vorherigen Verbesserungen der Konformität finden Sie unter Visual C++: Neuerungen von 2003 bis 2015.

Verbesserungen der Konformität in Visual Studio 2022, Version 17.2

Visual Studio 2022 17.2 enthält die folgenden Verbesserungen der Konformität, Fehlerbehebungen und Behavior Changes im Microsoft C++-Compiler.

Unterminierte bidirektionale Zeichenwarnungen

Visual Studio 2022 Version 17.2 fügt Ebene 3 Warnung C5255 für unterminierte Unicode bidirektionale Zeichen in Kommentaren und Zeichenfolgen hinzu. Die Warnung behandelt ein Sicherheitsproblem, das in Trojanische Quelle: Unsichtbare Sicherheitsrisiken von Nicholas Boucher und Ross Anderson beschrieben wird. Weitere Informationen zu Unicode bidirektionalen Zeichen finden Sie unter Unicode® Standard Anhang #9: UNICODE BIDIRECTIONAL ALGORITHM.

Warnung C5255 adressiert nur Dateien, die nach der Konvertierung Unicode bidirektionale Zeichen enthalten. Diese Warnung gilt für UTF-8-, UTF-16- und UTF-32-Dateien, sodass die richtige Quellcodierung bereitgestellt werden muss. Diese Änderung ist ein Breaking Change der Quelle.

Beispiel (vor/nach)

In Versionen von Visual Studio vor Visual Studio 2022 Version 17.2 hat ein unterminiertes bidirektionales Zeichen keine Warnung erzeugt. In Visual Studio 2022 Version 17.2 wird die Warnung C5255 generiert:

// bidi.cpp
int main() {
    const char *access_level = "user";
    // The following source line contains bidirectional Unicode characters equivalent to:
    //    if ( strcmp(access_level, "user\u202e \u2066// Check if admin \u2069 \u2066") ) {
    // In most editors, it's rendered as:
    //    if ( strcmp(access_level, "user") ) { // Check if admin
    if ( strcmp(access_level, "user‮ ⁦// Check if admin ⁩ ⁦") ) {
        printf("You are an admin.\n");
    }
    return 0;
}

/* build output
bidi.cpp(8): warning C5255: unterminated bidirectional character encountered: 'U+202e'
bidi.cpp(8): warning C5255: unterminated bidirectional character encountered: 'U+2066'
*/

from_chars()float Tiebreaker

Visual Studio 2022 Version 17.2 behebt einen Fehler in <charconv>from_chars()float Tiebreaker-Regeln, die falsche Ergebnisse erzeugt haben. Dieser Fehler hat dezimale Zeichenfolgen betroffen, die sich an der genauen Mitte der aufeinander folgenden float Werte befinden, innerhalb eines schmalen Bereichs. (Die kleinsten und größten betroffenen Werte waren 32768.009765625 bzw. 131071.98828125) Die Tiebreaker-Regel wollte auf "gerade" runden und "gerade" war nach „unten“, aber die Implementierung hat "nach oben" falsch gerundet. (double wurde nicht betroffen.) Weitere Informationen und Implementierungsdetails finden Sie unter microsoft/STL#2366.

Diese Änderung wirkt sich auf das Laufzeitverhalten im angegebenen Bereich von Fällen aus.

Beispiel

// from_chars_float.cpp
#include <cassert>
#include <charconv>
#include <cstdio>
#include <string_view>
#include <system_error>
using namespace std;
int main() {
    const double dbl  = 32768.009765625;
    const auto sv     = "32768.009765625"sv;
    float flt         = 0.0f;
    const auto result = from_chars(sv.data(), sv.data() + sv.size(), flt);
    assert(result.ec == errc{});
    printf("from_chars() returned: %.1000g\n", flt);
    printf("This rounded %s.\n", flt < dbl ? "DOWN" : "UP");
}

Versionen vor Version 17.2 von Visual Studio 2022:

C:\Temp>cl /EHsc /nologo /W4 /std:c++17 from_chars_float.cpp && from_chars_float
from_chars_float.cpp
from_chars() returned: 32768.01171875
This rounded UP.

In Visual Studio 2022, Version 17.2 und höher:

C:\Temp>cl /EHsc /nologo /W4 /std:c++17 from_chars_float.cpp && from_chars_float
from_chars_float.cpp
from_chars() returned: 32768.0078125
This rounded DOWN.

/Zc:__STDC__ stellt __STDC__ für C zur Verfügung

Der C-Standard erfordert, dass eine konforme C-Implementierung __STDC__ als 1 definiert. Aufgrund des Verhaltens der UCRT, die POSIX-Funktionen nicht verfügbar macht, wenn __STDC__1 ist, ist es nicht möglich, dieses Makro für C standardmäßig zu definieren, ohne Änderungen an den stabilen Sprachversionen einzuführen. Visual Studio 2022 Version 17.2 und höher fügen Sie eine Konformitätsoption hinzu, /Zc:__STDC__, die dieses Makro definiert. Es gibt keine negative Version der Option. Derzeit planen wir, diese Option standardmäßig für zukünftige Versionen von C zu verwenden.

Diese Änderung ist ein Breaking Change der Quelle. Es gilt, wenn der C11- oder C17-Modus aktiviert ist, /std:c11 oder /std:c17 zusammen mit /Zc:__STDC__.

Beispiel

// test__STDC__.c
#include <io.h>
#include <fcntl.h>
#include <stdio.h>

int main() {
#if __STDC__
    int f = _open("file.txt", _O_RDONLY);
    _close(f);
#else
    int f = open("file.txt", O_RDONLY);
    close(f);
#endif
}

/* Command line behavior

C:\Temp>cl /EHsc /W4 /Zc:__STDC__ test__STDC__.c && test__STDC__

*/

Warnung für fehlende Klammern

Warnung C5246 meldet fehlende Klammern während der aggregierten Initialisierung eines Unterobjekts. Vor Visual Studio 2022 Version 17.2 behandelte die Warnung nicht den Fall eines Anonymen struct oder union.

Diese Änderung ist ein Breaking Change der Quelle. Es gilt, wenn die standardmäßige Warnung C5246 aktiviert ist.

Beispiel

In Visual Studio 2022 Version 17.2 und höher verursacht dieser Code jetzt einen Fehler:

struct S {
   union {
      float f[4];
      double d[2];
   };
};

void f()
{
   S s = { 1.0f, 2.0f, 3.14f, 4.0f };
}

/* Command line behavior
cl /Wall /c t.cpp

t.cpp(10): warning C5246: 'anonymous struct or union': the initialization of a subobject should be wrapped in braces
*/

Um dieses Problem zu beheben, fügen Sie dem Initializer Klammern hinzu:

void f()
{
   S s = { { 1.0f, 2.0f, 3.14f, 4.0f } };
}

Verbesserungen der Konformität in Visual Studio 2022, Version 17.1

Visual Studio 2022 17.1 enthält die folgenden Verbesserungen der Konformität, Fehlerbehebungen und Behavior Changes im Microsoft C++-Compiler.

Erkennen von falsch formatiertem Erfassungsstandard in nicht lokalen Lambdaausdrücken

Der C++-Standard lässt nur zu, dass ein Lambdaausdruck im Blockbereich einen Erfassungsstandard hat. In Visual C++ 2022 Version 17.1 und höher erkennt der Compiler nun, wenn ein Erfassungsstandard in einem nicht lokalen Lambdaausdruck nicht zulässig ist. Es sendet eine neue Warnung auf Ebene 4, C5253.

Diese Änderung ist ein Breaking Change der Quelle. Sie gilt in jedem Modus, der den neuen Lambdaprozessor verwendet: /Zc:lambda, /std:c++20 oder /std:c++latest.

Beispiel

In Visual C++ 2022 Version 17.1 gibt dieser Code nun einen Fehler aus:

#pragma warning(error:5253)

auto incr = [=](int value) { return value + 1; };

// capture_default.cpp(3,14): error C5253: a non-local lambda cannot have a capture default
// auto incr = [=](int value) { return value + 1; };
//              ^

Um dieses Problem zu beheben, entfernen Sie den Erfassungsstandard:

#pragma warning(error:5253)

auto incr = [](int value) { return value + 1; };

C4028 ist jetzt C4133 für Funktion-zu-Zeiger-Vorgänge

Vor Visual Studio 2022 Version 17.1 hat der Compiler bei bestimmten Zeiger-zu-Funktion-Vergleichen im C-Code eine falsche Fehlermeldung ausgegeben. Die falsche Meldung wurde ausgegeben, wenn Sie zwei Funktionszeiger mit gleicher Argumentanzahl, aber inkompatiblen Typen verglichen. Jetzt wird eine andere Warnung ausgegeben, die die Zeiger-zu-Funktion-Inkompatibilität und nicht die Nichtübereinstimmung von Funktionsparametern meldet.

Diese Änderung ist ein Breaking Change der Quelle. Sie gilt, wenn Code in C kompiliert wird.

Beispiel

int f1(int); 
int f2(char*); 
int main(void) 
{ 
    return (f1 == f2); 
}
// Old warning:
// C4028: formal parameter 1 different from declaration
// New warning:
// C4113: 'int (__cdecl *)(char *)' differs in parameter lists from 'int (__cdecl *)(int)'

Fehler bei einem nicht abhängigen static_assert

Wenn der mit einem static_assert verknüpfte Ausdruck kein abhängiger Ausdruck ist, wertet der Compiler den Ausdruck in Visual Studio 2022 Version 17.1 und höher aus, sobald er geparsed wird. Wenn der Ausdruck als false ausgewertet wird, gibt der Compiler eine Fehlermeldung aus. Vorher führte der Compiler diese Analyse nicht durch, wenn sich der static_assert innerhalb des Textkörpers einer Funktionsvorlage (oder innerhalb des Textkörpers einer Memberfunktion einer Klassenvorlage) befand.

Diese Änderung ist ein Breaking Change der Quelle. Sie gilt in jedem Modus, der /Zc:permissive- oder /Zc:static_assert beinhaltet. Dieser Behavior Change kann mithilfe der Compileroption /Zc:static_assert- deaktiviert werden.

Beispiel

In Visual Studio 2022 Version 17.1 und höher verursacht dieser Code jetzt einen Fehler:

template<typename T>
void f()
{
   static_assert(false, "BOOM!");
}

Um dieses Problem zu beheben, machen Sie den Ausdruck abhängig. Beispiel:

template<typename>
constexpr bool dependent_false = false;

template<typename T>
void f()
{
   static_assert(dependent_false<T>, "BOOM!");
}

Mit dieser Änderung gibt der Compiler nur dann eine Fehlermeldung aus, wenn die Funktionsvorlage f instanziiert wird.

Verbesserungen der Konformität in Visual Studio 2022 17.0

Visual Studio 2022 17.0 enthält die folgenden Verbesserungen der Konformität, Fehlerbehebungen und Behavior Changes im Microsoft C++-Compiler.

Warnung zur Bitfeldbreite für den Enumerationstyp

Wenn Sie eine Instanz eines Enumerationstyps als Bitfeld deklarieren, muss die Breite des Bitfelds alle möglichen Werte der Enumeration aufnehmen. Andernfalls gibt der Compiler eine Diagnosemeldung aus. Betrachten Sie das folgende Beispiel:

enum class E : unsigned { Zero, One, Two };

struct S {
  E e : 1;
};

Ein*e Programmierer*in erwartet möglicherweise, dass ein S::e-Klassenmember alle der explizit benannten enum-Werte enthalten kann. Aufgrund der Anzahl der Enumerationselemente ist dies nicht möglich. Das Bitfeld kann den Bereich der explizit bereitgestellten Werte von E (konzeptuell die Domäne von E) nicht abdecken. Um das Problem zu lösen, dass die Bitfeldbreite für die Domäne der Enumeration nicht groß genug ist, wird eine neue (standardmäßig deaktivierte) Warnung zu MSVC hinzugefügt:

t.cpp(4,5): warning C5249: 'S::e' of type 'E' has named enumerators with values that cannot be represented in the given bit field width of '1'.
  E e : 1;
    ^
t.cpp(1,38): note: see enumerator 'E::Two' with value '2'
enum class E : unsigned { Zero, One, Two };
                                     ^

Dieses Compilerverhalten ist ein quellbezogener und binärer Breaking Change, der sich auf alle /std - und /permissive -Modi auswirkt.

Fehler beim geordneten Zeigervergleich mit nullptr oder 0

Der C++-Standard hat versehentlich einen geordneten Zeigervergleich mit nullptr oder 0 zugelassen. Beispiel:

bool f(int *p)
{
   return p >= 0;
}

Im WG21-Papier N3478 wurde dieser Fehler entfernt. Diese Änderung wurde jetzt in MSVC implementiert. Wenn das Beispiel mithilfe von /permissive- (und /diagnostics:caret ) kompilieren wird, wird der folgende Fehler ausgegeben:

t.cpp(3,14): error C7664: '>=': ordered comparison of pointer and integer zero ('int *' and 'int')
    return p >= 0;
             ^

Dieses Compilerverhalten ist ein quellbezogener und binärer Breaking Change, der sich auf Code auswirkt, der mithilfe von /permissive- in allen /std -Modi kompiliert wurde.

Siehe auch

Microsoft C/C++-Sprachkonformität