2017-07-25 1 views
10

Nous sommes en train de migrer de VS2013 à VS2017. Ci-dessous est un échantillon de code probablement pas si minime, mais c'est le meilleur que je pouvais faire. L'essentiel est qu'une valeur flottante spécifique est envoyée à une fonction, mais la fonction reçoit la mauvaise valeur - cela est dû à une non-concordance de registres dans la fonction appelante.S'agit-il d'un bogue d'optimisation Visual C++ ou ai-je un bogue dans mon code?

Ce code fonctionne incorrectement sur VC141 (VS 2017) et VC140 (VS 2015), mais fonctionne correctement sur VC120 (VS 2013) et sur la version clang qui vient construit avec VS 2017 (Clang avec Microsoft CodeGen (v141_clang_c2) - quelle que soit la version compatible avec clang).

Le problème se manifeste lors de la compilation pour la plate-forme x64 en version (avec optimisations). Lors de la suppression des optimisations, le code fonctionne bien, donc je suppose que c'est l'optimiseur. Le comportement incorrect est dans badFunc() lors de l'appel test().

Le code:

#include <iostream> 
#include <vector> 

struct FloatWrapper 
{ 
    FloatWrapper() : m_value(0) {} 
    explicit FloatWrapper(float value) : m_value(value) {} 
    float getValue() const { return m_value; } 

private: 
    float m_value; 
}; 

class Tester 
{ 
public: 

    virtual bool test(FloatWrapper elevation) const 
    { 
     std::cout << "Expected=" << m_expected.getValue() << ", received=" << elevation.getValue() << '\n'; 
     return elevation.getValue() == m_expected.getValue(); 
    } 

    Tester(FloatWrapper expected) : m_expected(expected) 
    { 
    } 

    FloatWrapper m_expected; 

}; 

struct DataBlock 
{ 
    FloatWrapper a, b; 
}; 

bool badFunc(const Tester& query, std::vector<DataBlock> blocks) 
{ 
    auto block = blocks[0]; 

    if (!query.test(block.b)) 
    { 
     std::cout << "Tried to send " << block.b.getValue() << '\n'; 
     return false; 
    } 

    return true; 
} 


int main(int argc, const char** argv) 
{ 
    DataBlock block; 
    block.b = FloatWrapper(0.2f); 

    Tester tester(block.b); 

    return badFunc(tester, { block }) ? 0 : 1; 
} 

ligne de commande du compilateur:

/GS /GL /W3 /Gy /Zc:wchar_t /Zi /Gm- /O2 /Fd"x64\Release\vc141.pdb" /Zc:inline /fp:precise /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /Gd /Oi /MD /Fa"x64\Release\" /EHsc /nologo /Fo"x64\Release\" /Fp"x64\Release\compiler_bug_vc14.pch" /diagnostics:classic 

ligne de commande Linker:

/OUT:"x64\Release\compiler_bug_vc14.exe" /MANIFEST /LTCG:incremental /NXCOMPAT /PDB:"x64\Release\compiler_bug_vc14.pdb" /DYNAMICBASE "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /DEBUG:FULL /MACHINE:X64 /OPT:REF /INCREMENTAL:NO /PGD:"x64\Release\compiler_bug_vc14.pgd" /SUBSYSTEM:CONSOLE /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"x64\Release\compiler_bug_vc14.exe.intermediate.manifest" /OPT:ICF /ERRORREPORT:PROMPT /NOLOGO /TLBID:1 
+1

Cela ressemble à un bogue du compilateur. Je pourrais reproduire ceci sur mon ordinateur. Vous devriez le signaler à Microsoft. –

+0

Cela me semble un bug, signaler un bug sur [connect.microsoft.com] (https://connect.microsoft.com/VisualStudio). –

+4

Ouvert un problème de connexion MS: https://connect.microsoft.com/VisualStudio/feedback/details/3138251/optimizer-bug-in-vc140-141-passing-the-wrong-float-value-to-a-function – Asaf

Répondre