Incorrect code generated for std::array::operator= in VC2010 SP1
-
Tuesday, July 10, 2012 3:37 PM
I'm reporting this bug here because Submit Feedback form doesn't accept VC2010 issues.
My problem happens in release Win32 build, compiler switches are:
/Zi /nologo /W3 /WX /MP /O2 /Oi /Oy- /GL /D "WIN32" /D "_SCL_SECURE_NO_WARNINGS" /D "NDEBUG" /D "_WINDOWS" /D "_VC80_UPGRADE=0x0710" /D "_WIN32" /D "_SECURE_SCL=0" /D "_HAS_ITERATOR_DEBUGGING=0" /D "_WINDLL" /D "_UNICODE" /D "UNICODE" /GF /Gm- /EHsc /MD /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /openmp /Gd /wd"4702" /analyze- /errorReport:queue
The minimal code snippet which reproduces the bug:
////////////////////////////////////////////////////////////////////////// struct Point { double m_value[3]; Point& operator=(const Point& i_point) { for(unsigned i=0;i<3;i++) m_value[i] = i_point.m_value[i]; return *this; } }; ////////////////////////////////////////////////////////////////////////// struct Foo { double m1; Point m2; }; ////////////////////////////////////////////////////////////////////////// typedef std::array<Foo, 5> ArrFoo; void MakeCopy(ArrFoo& o_y, const ArrFoo& i_x) { o_y = i_x; // BUG! } void ReproduceBug() { ArrFoo x, y; MakeCopy(y, x); }The assignment in the line marked "BUG!" corrupts the data in the array.
Looking into the assembly code shows the reason (notice wrong offsets at addresses 0FD827DD, 0FD827F5 and 0FD8281C):
std::tr1::array<Foo,5>::operator=:
0FD827A0 fld qword ptr [ecx]
0FD827A2 fstp qword ptr [eax]
0FD827A4 fld qword ptr [ecx+8]
0FD827A7 fstp qword ptr [eax+8]
0FD827AA fld qword ptr [ecx+10h]
0FD827AD fstp qword ptr [eax+10h]
0FD827B0 fld qword ptr [ecx+18h]
0FD827B3 fstp qword ptr [eax+18h]
0FD827B6 fld qword ptr [ecx+20h]
0FD827B9 fstp qword ptr [eax+20h]
0FD827BC fld qword ptr [ecx+28h]
0FD827BF fstp qword ptr [eax+28h]
0FD827C2 fld qword ptr [ecx+30h]
0FD827C5 fstp qword ptr [eax+30h]
0FD827C8 fld qword ptr [ecx+38h]
0FD827CB fstp qword ptr [eax+38h]
0FD827CE fld qword ptr [ecx+40h]
0FD827D1 fstp qword ptr [eax+40h]
0FD827D4 fld qword ptr [ecx+48h]
0FD827D7 fstp qword ptr [eax+48h]
0FD827DA fld qword ptr [ecx+50h]
0FD827DD fstp qword ptr [eax+30h]
0FD827E0 fld qword ptr [ecx+58h]
0FD827E3 fstp qword ptr [eax+58h]
0FD827E6 fld qword ptr [ecx+60h]
0FD827E9 fstp qword ptr [eax+60h]
0FD827EC fld qword ptr [ecx+68h]
0FD827EF fstp qword ptr [eax+68h]
0FD827F2 fld qword ptr [ecx+70h]
0FD827F5 fstp qword ptr [eax+30h]
0FD827F8 fld qword ptr [ecx+78h]
0FD827FB fstp qword ptr [eax+78h]
0FD827FE fld qword ptr [ecx+80h]
0FD82804 fstp qword ptr [eax+80h]
0FD8280A fld qword ptr [ecx+88h]
0FD82810 fstp qword ptr [eax+88h]
0FD82816 fld qword ptr [ecx+90h]
0FD8281C fstp qword ptr [eax+30h]
0FD8281F fld qword ptr [ecx+98h]
0FD82825 fstp qword ptr [eax+98h]
0FD8282B retAfter swapping the members of struct Foo
struct Foo { Point m2; double m1; };the bug disappears because the correct code is generated:
std::tr1::array<Foo,5>::operator=:
0FFA27A0 fld qword ptr [ecx]
0FFA27A2 fstp qword ptr [eax]
0FFA27A4 fld qword ptr [ecx+8]
0FFA27A7 fstp qword ptr [eax+8]
0FFA27AA fld qword ptr [ecx+10h]
0FFA27AD fstp qword ptr [eax+10h]
0FFA27B0 fld qword ptr [ecx+18h]
0FFA27B3 fstp qword ptr [eax+18h]
0FFA27B6 fld qword ptr [ecx+20h]
0FFA27B9 fstp qword ptr [eax+20h]
0FFA27BC fld qword ptr [ecx+28h]
0FFA27BF fstp qword ptr [eax+28h]
0FFA27C2 fld qword ptr [ecx+30h]
0FFA27C5 fstp qword ptr [eax+30h]
0FFA27C8 fld qword ptr [ecx+38h]
0FFA27CB fstp qword ptr [eax+38h]
0FFA27CE fld qword ptr [ecx+40h]
0FFA27D1 fstp qword ptr [eax+40h]
0FFA27D4 fld qword ptr [ecx+48h]
0FFA27D7 fstp qword ptr [eax+48h]
0FFA27DA fld qword ptr [ecx+50h]
0FFA27DD fstp qword ptr [eax+50h]
0FFA27E0 fld qword ptr [ecx+58h]
0FFA27E3 fstp qword ptr [eax+58h]
0FFA27E6 fld qword ptr [ecx+60h]
0FFA27E9 fstp qword ptr [eax+60h]
0FFA27EC fld qword ptr [ecx+68h]
0FFA27EF fstp qword ptr [eax+68h]
0FFA27F2 fld qword ptr [ecx+70h]
0FFA27F5 fstp qword ptr [eax+70h]
0FFA27F8 fld qword ptr [ecx+78h]
0FFA27FB fstp qword ptr [eax+78h]
0FFA27FE fld qword ptr [ecx+80h]
0FFA2804 fstp qword ptr [eax+80h]
0FFA280A fld qword ptr [ecx+88h]
0FFA2810 fstp qword ptr [eax+88h]
0FFA2816 fld qword ptr [ecx+90h]
0FFA281C fstp qword ptr [eax+90h]
0FFA2822 fld qword ptr [ecx+98h]
0FFA2828 fstp qword ptr [eax+98h]
0FFA282E retIs that a known issue? Is there a workaround for it?
Andrey
- Edited by Andy_s73 Monday, July 23, 2012 6:07 AM
All Replies
-
Tuesday, July 10, 2012 8:38 PMI'll see if I can draw Stephen Lavavej's eyes (Microsoft) to your post. I'm not sure if this falls into his department or not.
-
Tuesday, July 10, 2012 11:23 PM
This is an optimizer bug that doesn't involve std::array:
C:\Temp>type meow.cpp #include <stdio.h> struct Point { double dbls[3]; Point& operator=(const Point& other) { for (int i = 0; i < 3; ++i) { dbls[i] = other.dbls[i]; } return *this; } }; struct Foo { double db; Point pt; }; struct Bar { Foo foos[5]; }; int main() { Bar x = { { { 50, { { 60, 70, 80 } } }, { 51, { { 61, 71, 81 } } }, { 52, { { 62, 72, 82 } } }, { 53, { { 63, 73, 83 } } }, { 54, { { 64, 74, 84 } } } } }; Bar y = { }; y = x; for (int i = 0; i < 5; ++i) { printf("%f %f %f %f\n", y.foos[i].db, y.foos[i].pt.dbls[0], y.foos[i].pt.dbls[1], y.foos[i].pt.dbls[2] ); } } C:\Temp>cl Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. usage: cl [ option... ] filename... [ /link linkoption... ] C:\Temp>cl /EHsc /nologo /W4 /MT meow.cpp && meow meow.cpp 50.000000 60.000000 70.000000 80.000000 51.000000 61.000000 71.000000 81.000000 52.000000 62.000000 72.000000 82.000000 53.000000 63.000000 73.000000 83.000000 54.000000 64.000000 74.000000 84.000000 C:\Temp>cl /EHsc /nologo /W4 /MT /O2 meow.cpp && meow meow.cpp 50.000000 60.000000 70.000000 80.000000 51.000000 61.000000 74.000000 81.000000 52.000000 62.000000 0.000000 82.000000 53.000000 63.000000 0.000000 83.000000 54.000000 64.000000 0.000000 84.000000And it appears to be fixed in VC11:
C:\Temp>cl Microsoft (R) C/C++ Optimizing Compiler Version 17.00.50622 for x86 Copyright (C) Microsoft Corporation. All rights reserved. usage: cl [ option... ] filename... [ /link linkoption... ] C:\Temp>cl /EHsc /nologo /W4 /MT meow.cpp && meow meow.cpp 50.000000 60.000000 70.000000 80.000000 51.000000 61.000000 71.000000 81.000000 52.000000 62.000000 72.000000 82.000000 53.000000 63.000000 73.000000 83.000000 54.000000 64.000000 74.000000 84.000000 C:\Temp>cl /EHsc /nologo /W4 /MT /O2 meow.cpp && meow meow.cpp 50.000000 60.000000 70.000000 80.000000 51.000000 61.000000 71.000000 81.000000 52.000000 62.000000 72.000000 82.000000 53.000000 63.000000 73.000000 83.000000 54.000000 64.000000 74.000000 84.000000
If you can still repro this with VC11 RC, let me know (stl@microsoft.com) and I'll send it to the optimizer team.- Proposed As Answer by Helen ZhaoModerator Wednesday, July 18, 2012 3:02 AM
- Marked As Answer by Andy_s73 Monday, July 23, 2012 6:06 AM
-
Monday, July 23, 2012 6:21 AM
Thank you, Stephan!
As I'm forced to use VC10, could you please give more information about the exact conditions which trigger the bug?

