为什么一个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
期间仍然存在,外部代码也无法知道该方法没有返回,因此无法合法访问它leSleep()
正在执行,但是,外部代码会知道缓冲区仍然存在。