为什么一个C++;编译器仅在存在';写了这么多之后,没有代码了吗? 我正在检查VisualC++ 10优化能力,发现了一个相当奇怪的事情。这里的所有代码都是用/O2编译的

为什么一个C++;编译器仅在存在';写了这么多之后,没有代码了吗? 我正在检查VisualC++ 10优化能力,发现了一个相当奇怪的事情。这里的所有代码都是用/O2编译的,c++,visual-c++,optimization,compiler-construction,compiler-optimization,C++,Visual C++,Optimization,Compiler Construction,Compiler Optimization,在以下代码中: int _tmain(int argc, _TCHAR* argv[]) { char buffer[1024] = {}; MessageBoxA( 0, buffer, buffer, 0 ); memset( buffer, 0, sizeof( buffer ) ); return 0; } int _tmain(int argc, _TCHAR* argv[]) { char buffer[1024] = {}; Mes

在以下代码中:

int _tmain(int argc, _TCHAR* argv[])
{
    char buffer[1024] = {};
    MessageBoxA( 0, buffer, buffer, 0 );
    memset( buffer, 0, sizeof( buffer ) );
    return 0;
}
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;
}
return
之前对
memset()
的调用从机器代码中删除(我检查了反汇编)。这是完全合理的-如果之后没有读取
缓冲区
,那么
memset()
是无用的,如果开发人员真的想覆盖缓冲区,他们可以使用它

但是,在以下代码中:

int _tmain(int argc, _TCHAR* argv[])
{
    char buffer[1024] = {};
    MessageBoxA( 0, buffer, buffer, 0 );
    memset( buffer, 0, sizeof( buffer ) );
    return 0;
}
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;
}
int-tmain(int-argc,_-TCHAR*argv[]
{
字符缓冲区[1024]={};
MessageBoxA(0,buffer,buffer,0);
memset(buffer,0,sizeof(buffer));

Sleep(0);//编译器可能无法判断
MessageBoxA
没有创建
buffer
的别名,该别名随后将由
Sleep
使用。因此它无法通过“仿佛”检查。

编译器可以查看
memset
的内容并确定它的作用。
Sleep()
是一种与内核交互的系统调用,其行为取决于代码运行的Windows版本;包括尚未实现的Windows版本的可能性。编译器根本无法知道函数将执行什么操作,因此无法对其进行优化

MessageBox
也是如此,这让我很惊讶
memset
在第一个版本中被删除了


可以肯定的是,对
memset
的调用在任何当前或未来版本的Windows上都不会有问题,但我不想让编译器去猜测这一点。

你知道Sleep()没有副作用。编译器应该怎么知道呢?@HansPassant:
Sleep()怎么知道
是否会受到它不知道的局部变量的影响?@sharptooth:缓冲区的地址被传递给其他函数,这些函数可以将其存储为全局或静态变量,Sleep可以访问这些变量。在第一个版本中,
memset
是在
MessageBoxA
之后调用的。因此不会对其产生影响。我们可以争辩太长了,读不下去了,MessageBoxA的<代码> >可以把地址发布到正在观看的东西上,但是C++虚拟机没有定时保证,所以消除调用类似于在返回之前简单地等待无限时间。TL;在调用<代码> MyStuts<代码>之后的DR指令可能会影响优化器。@ Matthieu M.,我不这样做。同意。如果编译器能够确保本地缓冲区没有“泄漏”(即某些方法保存了它的地址),那么即使Sleep()是的,很明显,这将是一个死存储。
我的摘要听起来并不像它那样笼统。@Voo:如果外部代码得到了
缓冲区的别名(它可以通过
MessageBox
调用获得该别名)如果没有
Sleep
调用,即使
buffer
memset
期间仍然存在,外部代码也无法知道该方法没有返回,因此无法合法访问它le
Sleep()
正在执行,但是,外部代码会知道
缓冲区仍然存在。