G++编译含大型数组初始化器的代码时无报错中止的原因
GCC 12.2编译自定义复数类大型数组初始化时无报错中止
环境配置
- 系统:Windows 11
- IDE:Code::Blocks v20.03
- 编译器:MinGW64 g++ 12.2.0
测试代码
#define ROW { { 0.0, 0.0 }, { 1.0, 1.0 }, { 2.0, 2.0 }, { 3.0, 3.0 }, { 4.0, 4.0 }, \ { 5.0, 5.0 }, { 6.0, 6.0 }, { 7.0, 7.0 }, { 8.0, 8.0 }, { 9.0, 9.0 } } #define ROW8 ROW, ROW, ROW, ROW, ROW, ROW, ROW, ROW #define ROW64 ROW8, ROW8, ROW8, ROW8, ROW8, ROW8, ROW8, ROW8 #define ROW512 ROW64, ROW64, ROW64, ROW64, ROW64, ROW64, ROW64, ROW64 #define ROW4096 ROW512, ROW512, ROW512, ROW512, ROW512, ROW512, ROW512, ROW512 template <typename T> class cplx_t { public: T m_re; T m_im; cplx_t() : m_re(), m_im() { } cplx_t(const T& re, const T& im) : m_re(re), m_im(im) { } }; cplx_t<double> test_arr[2048][10] = { ROW512, ROW512, ROW512, ROW512 }; int main() { }
编译现象
- 编译上述代码时,g++无任何报错信息直接中止,不生成可执行文件。
- 移除
test_arr的初始化语句后,代码可正常编译通过。 - 将自定义
cplx_t替换为std::complex<double>时,带初始化的代码能正常编译。 - 通过编译器测试验证:GCC 12.2触发内部编译器错误;GCC 10.4、x86-64 Clang 15.0.0可正常编译;x86-64 Clang 3.0.0报类型不完整错误。
问题原因
这是GCC 12.2版本的内部编译器错误(ICE),属于编译器自身的逻辑缺陷:
- 自定义模板类
cplx_t的聚合初始化逻辑,在处理通过宏展开生成的超大型二维数组时,触发了GCC 12.2在数组初始化或模板类处理中的bug。 std::complex能正常编译是因为标准库对该类型做了特殊适配,编译器有专门的优化处理路径,避开了这个bug。- GCC 10.4及后续版本已修复该缺陷,因此可以正常编译。
解决方案
- 升级编译器版本:将GCC升级到10.4及以上的稳定版本,即可避开该bug。
- 更换编译器:临时改用Clang编译器编译这段代码。
- 修改初始化方式:避免使用宏展开的静态数组初始化,改用动态分配内存+循环赋值的方式初始化数组,例如:
cplx_t<double>* test_arr = new cplx_t<double>[2048 * 10]; for (int i = 0; i < 2048; ++i) { for (int j = 0; j < 10; ++j) { test_arr[i * 10 + j] = cplx_t<double>(j, j); } } // 使用完记得释放内存 delete[] test_arr;
内容的提问来源于stack exchange,提问作者raku99
相关产品推荐
相关产品推荐

