你能用ctime重现或解释这个Visual C ++错误吗?

时间:2014-10-04 02:55:19

标签: c++ visual-studio-2013 std

在发布模式下使用Visual Studio Professional 2013 Update 3编译时,time: 0将输出N,无论#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; } 的值是什么,都是32位和64位选项:

time

在rextester.com上使用gcc,clang和其他版本的vc ++进行测试时,它的行为正确,输出g()大于零。有什么线索在这里发生了什么?

我注意到内联t0函数会恢复正确的行为,但更改rt1和{{1}}的声明和初始化顺序不会。

1 个答案:

答案 0 :(得分:9)

如果使用调试器查看反汇编挡板,您可以看到生成的代码。对于VS2012 express在发布模式下,您可以获得:

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]  

从前4行汇编中可以看到,clockds:[0AF30E0h])的两次调用都发生在调用g之前。因此,在这种情况下,g花费多长时间并不重要,结果只会显示这两个连续调用之间的时间。

似乎VS确定g没有任何可能影响clock的副作用,因此可以安全地移动呼叫。

正如Michael Petch在评论中指出的那样,将volatile添加到r的声明中将阻止编译器移动呼叫。