避免编译器优化掉代码

c++代码编译成Release版本,编译器会做一些优化,生成的二进制可执行文件执行更快,体积更小。这种优化会复用栈上不同变量的空间,导致调试的时候,有些局部变量看不到了。比如如下代码:

int main()
{
  int ia = 1;
  ia++;
  int ib = ia++;
  ib++;
  int ic = ia - ib;
  ic++;
  printf("%d", ic);
  system("pause");
  return 0;
}

在调试的的时候,调试器直接运行到printf(“%d”, ic);这一行,而ia,ib,ic这些局部变量统统被优化了看不到,如下图所示: windbg snapshot optimize

如果程序在某个地方崩溃了,而崩溃地方的局部变量恰好被编译器优化掉了,调试的时候看堆栈的变量值几乎没有什么价值。chromium的base库里里面有个解决办法,就是把局部变量传给Alias,Alias函数的实现如下:

#pragma optimize("", off)
void Alias(const void* var) {
}
#pragma optimize("", on)

Alias函数其实不对传进来的局部变量做什么,只是函数内的代码实现禁用了编译器优化,这样调试的时候就可以看到局部变量来,效果如下: disable windbg snapshot optimize

这样就在#pragma optimize("", off)#pragma optimize("", off)之间的c++代码不被编译器优化了。

#pragma optimize是微软vc++编译器的开关,如果要对clang编译器实现同样的效果,可以使用下面的代码:

#if defined(COMPILER_MSVC)
#pragma optimize("", off)
#elif defined(__clang__)
#pragma clang optimize off
#endif

void Alias(const void* var) {
}

#if defined(COMPILER_MSVC)
#pragma optimize("", on)
#elif defined(__clang__)
#pragma clang optimize on
#endif

参考: