C++ C++;11:g++-4.7内部编译器错误

C++ C++;11:g++-4.7内部编译器错误,c++,linux,gcc,c++11,g++,C++,Linux,Gcc,C++11,G++,以下代码: #include <iostream> #include <array> using namespace std; constexpr int N = 1000000; constexpr int f(int x) { return x*2; } typedef array<int, N> A; template<int... i> struct F { static constexpr A f() { return A{{ ::

以下代码:

#include <iostream>
#include <array>
using namespace std;

constexpr int N = 1000000;
constexpr int f(int x) { return x*2; }

typedef array<int, N> A;

template<int... i> struct F { static constexpr A f() { return A{{ ::f(i)... }}; } };

template<class A, class B> struct C {};
template<int... i, int... j> struct C<F<i...>, F<j...>> : F<i..., (sizeof...(i)+j)...>
{
        using T = F<i..., (sizeof...(i)+j)...>;
};

template<int n> struct S : C<typename S<n/2>::T, typename S<n-n/2>::T> {};
template<> struct S<1> : F<0> { using T = F<0>; };

constexpr auto X = S<N>::f();

int main()
{
        cout << X[3] << endl;
}

出了什么问题?

内部错误意味着您遇到了编译器错误。

您的程序似乎需要不合理的内存量(可能是因为太多的模板扩展)

使用最近的
g++-trunk

gcc version 4.8.0 20121026 (experimental) [trunk revision 192860] (GCC) 
具有以下zsh限制:

   % limit          
   cputime         unlimited
   filesize        unlimited
   datasize        15000MB
   stacksize       8MB
   coredumpsize    400MB
   memoryuse       15000MB
   maxproc         128166
   descriptors     1024
   memorylocked    64kB
   addressspace    16000MB
   maxfilelocks    unlimited
   sigpending      128166
   msgqueue        819200
   nice            0
   rt_priority     0
   rt_time         unlimited
(这是在带有i3770K intel处理器和16Gb RAM的Debian/Sid/AMD64上实现的)

我得到:

  % time g++-trunk -std=gnu++11 andrew.cc -o andrew
  virtual memory exhausted: Cannot allocate memory
  g++-trunk -std=gnu++11 andrew.cc -o andrew :
  108.25s user 3.28s system 89% cpu 2:03.98 total
所以,模板扩展似乎需要太多内存,所以您的程序是不合理的

我不确定这是否会被接受为GCC错误。C++模板的宏扩展是图灵完成,你刚碰到了墙。GCC主干确实报告了一个致命但可以理解的错误


这个故事的寓意可能是适当地(限制与您的系统和硬件兼容),可能使用
limit
zsh内置或
ulimit
bash内置。

在4.7.1上,我有
cc1plus:在总共401997824字节之后,内存不足分配1048576字节。看起来像是一个编译器错误。我在4.7.2上,有32GB的内存。这两者中的任何一个都可以解释差异。可能是因为这里有8GB,但是当减小
N
的值时,它就会正确编译。@Andrew Tomazos:是的;请花点时间报告一下这个bug,我想知道~10^6次扩展到底会消耗32GB的内存。递归深度很小,否则将达到512深度限制。它适用于N=10000,因此看起来它似乎在以某种方式使用O(N^2)空间,但它应该只使用O(NlogN)空间。原因很简单:编译器希望(对大多数用户来说应该)在其内部表示中保留大量数据。因此,实际的扩展发生在内部表示(Gcc-Generic)上,它比您想象的更复杂(例如,因为它记住每件事情的源位置)。记住源位置不足以解释资源需求的渐进增长。对于像这个一样大的持续爆炸,GCC每次实例化大约需要32kb,这是荒谬的。然后请通过提交相关补丁来贡献给GCC。clang++编译了这个(在增加-fconstexpr步骤后),在大约1.5G内存中,在10秒内没有问题。g++生长到15G,约4分钟后死亡。(是的,经过这么多年,它仍然这样做)。
  % time g++-trunk -std=gnu++11 andrew.cc -o andrew
  virtual memory exhausted: Cannot allocate memory
  g++-trunk -std=gnu++11 andrew.cc -o andrew :
  108.25s user 3.28s system 89% cpu 2:03.98 total