c++ - usar - visual studio no muestra errores
¿Es un error del optimizador de Visual C++ o tengo un error en mi código? (1)
La respuesta es sí, es un error del optimizador. Microsoft dice que lo arreglaron y que actualmente (24 de septiembre de 2016) está pendiente de publicación.
Estamos en el proceso de migrar de VS2013 a VS2017.
A continuación hay una muestra de código probablemente no tan mínima, pero es lo mejor que puedo hacer. La esencia de esto es que se envía un valor flotante específico a una función, pero la función recibe el valor incorrecto, esto se debe a una falta de coincidencia de registros en la función de llamada.
Este código se ejecuta incorrectamente en VC141 (VS 2017) y VC140 (VS 2015), pero se ejecuta correctamente en VC120 (VS 2013) y en la versión de clang que viene incorporada con VS 2017 (Clang con Microsoft CodeGen (v141_clang_c2) - lo que sea compatible con clang versión es).
El problema se manifiesta al compilar para la plataforma x64 en Release (con optimizaciones). Al eliminar optimizaciones, el código funciona bien, así que supongo que es el optimizador. El comportamiento incorrecto es en badFunc()
cuando se llama a test()
.
El código:
#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;
}
Línea de comando del compilador:
/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
Línea de comando del enlazador:
/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