2014-01-10 9 views
25

Dieses Programm, das, wenn es mit VC12 (in Visual Studio 2013 RTM) [1] führt zu einem Absturz zusammengestellt (in allen Konfigurationen bauen), wenn es sollte wirklich nicht:(Bekannter) Compiler Fehler in VC12?

#include <string> 

void foo(std::string const& oops = {}) 
{ 
} 

int main() 
{ 
    foo(); 
} 

ich von zwei kennen silent schlecht codegen Bugs dass könnte bezogen werden:

Ehrlich gesagt denke ich, dass diese anders sind. Weiß jemand,

  1. , ob es ein aktiv verfolgt Bug auf connect für diese
  2. , ob es eine Abhilfe (oder eine explizite Beschreibung der Situation, die diesen Fehler verursacht, so können wir es suchen/es vermeiden in unserer Code-Basis)?

[1] nur ein leeres Projekt erstellen die C++ Console Application 'Assistenten' verwenden. Der Einfachheit halber deaktivieren Sie vorkompilierte Header und belassen alle Standardwerte: http://i.stack.imgur.com/rrrnV.png

+2

'return 0;' fehlt, scheint aber nicht verwandt zu sein ... – Mario

+16

@Mario, nicht erforderlich. Auch nicht verwandt. – sehe

+2

@Sehe was über https://connect.microsoft.com/VisualStudio/feedback/details/809243/c-11-initializer-lists-as-default-argument? Ich weiß nicht, ob es relevant oder verwandt ist. –

Antwort

8

Ein aktives Problem wurde in November zurückgeschickt. Der eingegebene Beispielcode war:

Compile and run following code in VS2013 

#include <string> 

void f(std::string s = {}) { 
} 

int main(int argc, char* argv[]) { 
    f(); 
    return 0; 
} 

Der Fehler wurde von Microsoft bestätigt.

Dort scheint es keine Umgehung zu geben. bearbeiten Umgehungen leicht auf die Vermeidung der Listen initializer Syntax basiert:

void f(std::string s = ""); 
void f(std::string s = std::string()); 
void f(std::string s = std::string {}); 

Oder einfach auf die altmodische Art (wenn Sie nicht die Einführung Überlastungen nichts dagegen):

void f(std::string s); 
void f() { f(std::string()); } 
+0

Ich habe die offensichtlichen Problemumgehungen hinzugefügt. Dies beantwortet etwas die Frage, wonach zu suchen ist.Ich nehme an, dass grepping für '= {}' oder '{{}', ', {}' einen Weg findet, das Vorkommen zu finden. Ich bin nicht völlig beruhigt, dass dies (alle) relevante Call Sites finden wird. – sehe

11

Es sieht aus wie Visual Studio ist nur in Bezug auf den Konstruktor unterbrochen, den es aufruft, wenn das Standardargument eine Initialisierungsliste ist.Dieser Code:

#include <iostream> 

struct test { 
    test() { std::cout << "test()" << std::endl ; } 
    test (int) { std::cout << "test (int)" << std::endl ; } 
}; 

void func(test const &s = {}) 
{ 
} 

int main() 
{ 
    test s = {} ; 
    func() ; 
} 

produziert dieses Ergebnis in gcc und clang finden es live here:

test() 
test() 

während Visual Studio produziert dieses Ergebnis:

test() 
test (int) 

und für diesen Code:

#include <iostream> 
#include <initializer_list> 

struct test { 
    test() { std::cout << "test()" << std::endl ; }; 

    test (int) { std::cout << "test (int)" << std::endl ; }; 
    test (std::initializer_list<int>) { std::cout << "test (initializer_list<int>)" << std::endl ; } ; 
}; 

void func(test const &s = {0}) 
{ 
} 

int main() 
{ 
    test s = {0} ; 
    func() ; 
} 

gcc und clang produzieren diese Resultat es live here sehen:

test (initializer_list<int>) 
test (initializer_list<int>) 

während Visual Studio diesen Fehler erzeugt:

error C2440: 'default argument' : cannot convert from 'initializer-list' to 'const test &' 
    Reason: cannot convert from 'initializer-list' to 'const test' 
    No constructor could take the source type, or constructor overload resolution was ambiguous 

aktualisieren

Für eine Plausibilitätsprüfung, ging ich in den Rücken Standard, um sicherzustellen, dass es nicht irgendeine ungerade Regel an der Wurzel dieses Unterschieds gab oder vielleicht Ich Einschränkung, die diesen Code macht schlecht gebildet. Soweit ich das beurteilen kann, ist dieser Code nicht schlecht gebildet. Abschnitt 8.3.5 Grammatik erlaubt dies ausdrücklich:

parameter-declaration: 
    attribute-specifier-seqopt decl-specifier-seq declarator 
    attribute-specifier-seqopt decl-specifier-seq declarator = initializer-clause 
    [...] 

Es scheint wie Abschnitt nicht 8.5Initializers oder 8.3.6Standard Argumente keine Einschränkungen hinzufügen, aber diesen Mangel Bericht 994. braced-init-list as a default argument und Arbeitspapier Wording for brace-initializers as default arguments es, dass es klar machen sollte und Umreißen Sie die Änderungen an der Norm, um es zu ermöglichen, und mit Blick auf die Deltas gibt es keine offensichtlichen Einschränkungen.

+0

Ich würde dies über https://connect.microsoft.com/VisualStudio/feedback/details/809243/c-11-initializer-lists-as-default-argument auch kommentieren, nur für den Fall, dass sie Hilfe brauchen:/(Nun, vielleicht brauchen sie Hilfe, um zu erkennen, dass dieser Bug störend ist) – sehe

+1

@sehe Kommentar zum Fehlerbericht hinzugefügt –