优化在堆上创建的冗余变量

时间:2018-07-12 10:35:36

标签: c++ optimization

我设置了o2编译器标志。在多个平台/编译器上测试。完全不使用这两个变量。

const char * temp1 = "a";// optimised away
char * temp2 = new char[1];//not optimised.

第一个变量由于多余而被编译器删除。第二个变量反之。 编译器是否无法检测到该内存块在程序中无处使用?

最初的问题来自真正的产品,当我注意到临时的,未使用的std :: string长度超过15个符号并作为函数的参数传递时,并未得到优化。

asm在线查看: https://godbolt.org/g/Shmx92

编辑: 正如Jarod42提到的那样,clang可以优化两个变量。

2 个答案:

答案 0 :(得分:0)

char * temp2 = new char[1];

在这种情况下,您将运算符称为new(sizeof(char)* 1) 实际上是new运算符-是函数的声明(vcruntime_new.h库)。编译后,“ new char [1]”语句将在调用时被替换(asm函数地址)。链接器会将此调用与.obj或.dll中运算符新函数的实际地址绑定在一起。 这就是为什么编译器没有机会知道执行运算符新功能和 它不会优化此语句。

void foo()
{
    const char* str = "";
}

void buz()
{
    char* str = new char[1];
}

反汇编此功能(无优化):

?foo@@abrakadabra (void __cdecl foo(void)): ; foo's signature
mov dword ptr[ebp - 4], offset $...         ; insted ... offset link to table of symbols
;...

?buz@@abrakadabra (void __cdecl buz(void)): ; buz's signature
call ??_U@...     ; insted ... mnemonic name of operator new function
mov dword ptr [ebp - 4], eax    ; this is simplification

在语句“ call ...”中,编译器无法知道此功能的真正作用。这是链接程序的任务。

备注:汇编程序中的某些代码已简化,以更好地理解

答案 1 :(得分:0)

第一个变量

  return redirect()->route('toAnotherController',[$var]);

不在堆上,而是指向只读数据部分。创建字符串“ a”没有副作用,编译器可以安全地对其进行优化。

第二个变量

const char * temp1 = "a";// optimised away
另一方面,

呼叫char * temp2 = new char[1];//not optimised. 。这可能会超载,或者可能在libc中设置了一些malloc挂钩,从而产生了副作用。优化这一点将改变程序的行为。编译器知道new何时被重载,并且可以假设它知道底层libc的功能(clang似乎)。但是说我确实设置了一个malloc钩子,然后行为突然改变了。我认为clang无法优化调用效果。

其次,由于您泄漏内存,该代码已损坏。至少应使用temp2调用delete。因此,像您这样的情况永远都不会出现在真实代码中。优化器必须同时看到new和delete调用并确定:

  1. 指针永远不会在其他任何地方使用
  2. 删除总是在调用new时被调用

我还发现您不太可能分配内存然后不使用它。为什么不简单地将变量初始化为nullptr?

优化通常会覆盖经常使用的明智代码。