Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 这是gcc优化器中的错误吗?_C++_C++14 - Fatal编程技术网

C++ 这是gcc优化器中的错误吗?

C++ 这是gcc优化器中的错误吗?,c++,c++14,C++,C++14,当我用gcc6-O3-std=c++14编译下面的代码时,我得到了一个很好的空main: Dump of assembler code for function main(): 0x00000000004003e0 <+0>: xor %eax,%eax 0x00000000004003e2 <+2>: retq 函数main()的汇编程序代码转储: 0x00000000004003e0:xor%eax,%eax 0x00000000

当我用gcc6-O3-std=c++14编译下面的代码时,我得到了一个很好的空
main

Dump of assembler code for function main():
   0x00000000004003e0 <+0>:     xor    %eax,%eax
   0x00000000004003e2 <+2>:     retq 
函数main()的汇编程序代码转储: 0x00000000004003e0:xor%eax,%eax 0x00000000004003e2:retq 但取消注释主“中断”优化中的最后一行:

Dump of assembler code for function main():
   0x00000000004005f0 <+0>:     sub    $0x78,%rsp
   0x00000000004005f4 <+4>:     lea    0x40(%rsp),%rdi
   0x00000000004005f9 <+9>:     movq   $0x400838,0x10(%rsp)
   0x0000000000400602 <+18>:    movb   $0x0,0x18(%rsp)
   0x0000000000400607 <+23>:    mov    %fs:0x28,%rax
   0x0000000000400610 <+32>:    mov    %rax,0x68(%rsp)
   0x0000000000400615 <+37>:    xor    %eax,%eax
   0x0000000000400617 <+39>:    movl   $0x0,(%rsp)
   0x000000000040061e <+46>:    movq   $0x400838,0x30(%rsp)
   0x0000000000400627 <+55>:    movb   $0x0,0x38(%rsp)
   0x000000000040062c <+60>:    movl   $0x0,0x20(%rsp)
   0x0000000000400634 <+68>:    movq   $0x400838,0x50(%rsp)
   0x000000000040063d <+77>:    movb   $0x0,0x58(%rsp)
   0x0000000000400642 <+82>:    movl   $0x0,0x40(%rsp)
   0x000000000040064a <+90>:    callq  0x400790 <ErasedObject::~ErasedObject()>
   0x000000000040064f <+95>:    lea    0x20(%rsp),%rdi
   0x0000000000400654 <+100>:   callq  0x400790 <ErasedObject::~ErasedObject()>
   0x0000000000400659 <+105>:   mov    %rsp,%rdi
   0x000000000040065c <+108>:   callq  0x400790 <ErasedObject::~ErasedObject()>
   0x0000000000400661 <+113>:   mov    0x68(%rsp),%rdx
   0x0000000000400666 <+118>:   xor    %fs:0x28,%rdx
   0x000000000040066f <+127>:   jne    0x400678 <main()+136>
   0x0000000000400671 <+129>:   xor    %eax,%eax
   0x0000000000400673 <+131>:   add    $0x78,%rsp
   0x0000000000400677 <+135>:   retq   
   0x0000000000400678 <+136>:   callq  0x4005c0 <__stack_chk_fail@plt>
函数main()的汇编程序代码转储: 0x00000000004005f0:子$0x78,%rsp 0x00000000004005f4:lea 0x40(%rsp),%rdi 0x00000000004005f9:movq$0x400838,0x10(%rsp) 0x00000000000400602:movb$0x0,0x18(%rsp) 0x00000000000400607:mov%fs:0x28,%rax 0x000000000040610:mov%rax,0x68(%rsp) 0x00000000000400615:xor%eax,%eax 0x00000000000400617:movl$0x0,(%rsp) 0x0000000000040061E:movq$0x400838,0x30(%rsp) 0x00000000000400627:movb$0x0,0x38(%rsp) 0x000000000040062c:movl$0x0,0x20(%rsp) 0x00000000000400634:movq$0x400838,0x50(%rsp) 0x0000000000040063D:movb$0x0,0x58(%rsp) 0x00000000000400642:movl$0x0,0x40(%rsp) 0x000000000040064a:callq 0x400790 0x0000000000040064F:lea 0x20(%rsp),%rdi 0x00000000000400654:callq 0x400790 0x0000000000400659:mov%rsp,%rdi 0x00000000004065C:callq 0x400790 0x00000000000400661:mov 0x68(%rsp),%rdx 0x00000000000400666:xor%fs:0x28,%rdx 0x000000000040066f:jne 0x400678 0x00000000000400671:xor%eax,%eax 0x00000000000400673:添加$0x78,%rsp 0x0000000000400677:retq 0x00000000000400678:callq 0x4005c0 代码

#包括
#包括
名称空间
{
结构擦除类型表
{
使用析构函数_t=void(*)(void*obj);
析构函数;
};
模板
无效数据或(无效*obj)
{
返回静态_cast(obj)->~T();
}
模板
静态常量橡皮擦类型表橡皮擦类型表={
&dtor
};
}
结构擦除对象
{
std::aligned_storage::type storage;
常量擦除类型vtable&vtbl;
布尔标志=假;
模板
橡皮擦对象(T&obj)
:vtbl(已擦除类型vtable)
{

static_assert(sizeof(T)我使用
-fdump ipa inline运行了
g++
,以获取有关函数内联或不内联原因的更多信息

对于使用main()函数和创建的三个对象的testcase,我得到:

  (...)
  150 Deciding on inlining of small functions.  Starting with size 35.
  151 Enqueueing calls in void {anonymous}::dtor(void*) [with T = myType]/40.
  152 Enqueueing calls in int main()/35.
  153   not inlinable: int main()/35 -> ErasedObject::~ErasedObject()/33, call is unlikely and code size would grow
  154   not inlinable: int main()/35 -> ErasedObject::~ErasedObject()/33, call is unlikely and code size would grow
  155   not inlinable: int main()/35 -> ErasedObject::~ErasedObject()/33, call is unlikely and code size would grow
  (...)
此错误代码在gcc/gcc/ipa inline.c中设置:

  else if (!e->maybe_hot_p ()
       && (growth >= MAX_INLINE_INSNS_SINGLE
       || growth_likely_positive (callee, growth)))
{
      e->inline_failed = CIF_UNLIKELY_CALL;
      want_inline = false;
}
然后我发现,使g++内联这些函数的最小更改是添加一个声明:

int main() __attribute__((hot));
我无法在代码中找到为什么
intmain()
不被认为是热门的,但这可能应该留给另一个问题

更有趣的是我上面粘贴的条件的第二部分,其目的是在代码增长时不内联,并且您生成了一个在完全内联后代码收缩的示例


我认为这值得一提,但我不确定你是否可以称之为bug——内联影响的估计是一种启发式方法,因此它在大多数情况下都能正常工作,而不是在所有情况下。

在我看来像个bug。在GCC(Ubuntu 5.3.1-14ubuntu2)5.3.1 20160413GCC不内联
main()<代码> >积极地尝试调用它>代码> MEOW。MaIEJCECORCA可能因为<代码>主< /代码>不应该是热的,并且指令缓存受到内联和展开的影响。我认为我知道一点C++……我看不出代码的一半:(我认为运行A来获得最小值是一个有趣的实验。l无法内联的示例。我猜
main()
不被认为是热门的,因为显式调用或通过指针调用它是未定义的行为(C++11 3.6.1/3:“函数main不能在程序中使用”)。所以gcc“知道”这一点
main()
只能被调用一次。@MichaelBurr关于未定义的行为,你是完全正确的,但由于我在GCC源代码中找不到使
main()
变冷的原因,我仍然“不知道:)我在
中没有看到特殊情况,可能是热/冷启发本身。
int main() __attribute__((hot));