我正在检查Visual C++ 10优化功能,发现了一件很奇怪的事情。本文中的所有代码均使用/O2进行编译。

在下面的代码中:

int _tmain(int argc, _TCHAR* argv[])
{
    char buffer[1024] = {};
    MessageBoxA( 0, buffer, buffer, 0 );
    memset( buffer, 0, sizeof( buffer ) );
    return 0;
}

从机器代码中删除memset()之前对return的调用(我检查了反汇编)。这是完全合理的-如果此后没有读取buffer,则memset()没用,如果开发人员真的想覆盖缓冲区,则可以使用 SecureZeroMemory() 代替。

但是在以下代码中:
int _tmain(int argc, _TCHAR* argv[])
{
    char buffer[1024] = {};
    MessageBoxA( 0, buffer, buffer, 0 );
    memset( buffer, 0, sizeof( buffer ) );
    Sleep( 0 ); //<<<<<<<<<<<<<<<<<<<<<<<<<<< Extra code
    return 0;
}

没有消除对memset()的调用。该调用对观察到的行为没有影响,可以像在第一个代码段中一样被消除。

这可能是编译器缺陷,也可能是有用的-我无法决定。

为什么在第二个代码段发出的机器代码中留下memset()调用会有用吗?

最佳答案

编译器可能无法说出MessageBoxA并未为buffer创建别名,该别名随后会被Sleep使用。因此,它无法通过“假设”检查。

10-07 19:12
查看更多