Can you reproduce or explain this Visual C ++ error using ctime?

This code example will output time: 0 regardless of the value of N when compiling with Visual Studio Professional 2013 Update 3 in release mode, both 32 and 64-bit:

 #include <iostream> #include <functional> #include <ctime> using namespace std; void bar(int i, int& x, int& y) {x = i%13; y = i%23;} int g(int N = 1E9) { int x, y; int r = 0; for (int i = 1; i <= N; ++i) { bar(i, x, y); r += x+y; } return r; } int main() { auto t0 = clock(); auto r = g(); auto t1 = clock(); cout << r << " time: " << t1-t0 << endl; return 0; } 

When testing with gcc, clang and another version of vC ++ on rextester.com, it behaves correctly and displays time greater than zero. Any clues what is going on here?

I noticed that embedding the function g() restores the correct behavior, but changing the order of the declaration and initialization of t0 , r and t1 does not.

+6
source share
1 answer

If you look at disassembling winddow using a debugger, you will see the generated code. For VS2012 Express in release mode, you will receive the following:

 00AF1310 push edi auto t0 = clock(); 00AF1311 call dword ptr ds:[0AF30E0h] 00AF1317 mov edi,eax auto r = g(); auto t1 = clock(); 00AF1319 call dword ptr ds:[0AF30E0h] cout << r << " time: " << t1-t0 << endl; 00AF131F push dword ptr ds:[0AF3040h] 00AF1325 sub eax,edi 00AF1327 push eax 00AF1328 call g (0AF1270h) 00AF132D mov ecx,dword ptr ds:[0AF3058h] 00AF1333 push eax 00AF1334 call dword ptr ds:[0AF3030h] 00AF133A mov ecx,eax 00AF133C call std::operator<<<std::char_traits<char> > (0AF17F0h) 00AF1341 mov ecx,eax 00AF1343 call dword ptr ds:[0AF302Ch] 00AF1349 mov ecx,eax 00AF134B call dword ptr ds:[0AF3034h] 

from the first 4 lines of the assembly, you can see that two calls to clock ( ds:[0AF30E0h] ) occur before the call to g . Therefore, in this case it does not matter how long g takes, the result will only show the time between these two consecutive calls.

It seems that VS has determined that g has no side effects that would affect clock , so it's safe to move calls.

As Michael Patch notes in the comments, adding volatile to to the r declaration will stop the compiler from moving the call.

+9
source

Source: https://habr.com/ru/post/976236/


All Articles