在类模板上使用 arm gcc 编译期间的隔离错误

Segfault during compilation with arm gcc on class template

本文关键字:编译 错误 隔离 gcc arm      更新时间:2023-10-16

>我有一个实现中值过滤器的类模板。模板参数是数据类型和筛选器长度。

在使用基于 gcc 4.8.3 的 arm-none-eabi-g++ 编译时,我遇到了一个段错误。代码使用 Clang 5.0.1 或 Gcc 7.3.0 编译时没有警告。

我正在为 c++11 编译。

是我的代码有问题,还是真的是 gcc 错误?如果有错误,是否有方便的解决方法?即使不是错误,我也将不胜感激任何改进建议。

我能想到的事情可能是原因(尽管我认为它们都应该是允许的(:

  • 在此类中声明了一个结构,其成员之一是指向结构类型本身的指针
  • 此类具有两个静态 constexpr 成员数据元素

法典

声明

// In MedianFilter.h
template <typename dType, int len>
class MedianFilter
{
public:
dType read() { return xMed_; }
dType update(dType x);
private:
struct pair
{
pair* nextSmallest;
dType xi;
};
static constexpr dType stopper_ {0};
static constexpr int filterLen_ {len};
pair buffer_[filterLen_] = {};
pair* datpoint = buffer_;   
pair small_ = {nullptr, stopper_};
pair big_ = {&small_, stopper_};
dType xMed_ {stopper_};
};

定义(在 .h 文件中(未显示

主.cpp

#include <cstdint>
using std::uint16_t;
#include "MedianFilter.h"
int main() {
MedianFilter<uint16_t, 7> filt;
filt.update(0);
return 0;
}

错误输出:

In file included from main.cpp:1:0: MedianFilter.h: In constructor
'constexpr MedianFilter<short unsigned int, 7>::MedianFilter()':
MedianFilter.h:22:7: internal compiler error: Segmentation fault 
class MedianFilter
Please submit a full bug report, with preprocessed source if appropriate. See <http://gcc.gnu.org/bugs.html> for instructions.

在@einpoklum的回答中描述,这是一个在 gcc 4.9.1 中修复的编译器错误。解决方法相当简单 - 省略结构数组的大括号初始化并以其他方式实现您的设计意图。例如,可以在结构的定义中提供默认成员初始值设定项。

使用 C++11,可以在类定义中初始化类成员。编译器段错误是通过将此功能与结构数组一起使用而触发的,其中数组大小派生自模板参数:

pair buffer_[filterLen_] = {};

AFAIK,从 C++11 开始,此表达式应使用空初始值设定项列表对类成员数组进行聚合初始化。这等效于通过空列表 {} 初始化每个数组元素,该列表对各个结构执行聚合初始化(同样使用空初始值设定项列表(。

出于某种原因,此语法会导致编译器出现段错误。4.9.1 之前的 gcc 的解决方法只是避免这种语法。

导致分段错误的不是你的代码,而是你的编译器抓住了自己的分段错误,并给了你一个信息量更大的错误。

通常,当进程执行分段错误时,即尝试以未经授权的方式访问内存段,将调用默认信号处理程序,您看到的内容如下:

Segmentation fault (core dumped)

在进程退出时打印到标准错误流。但是一个进程(不仅仅是编译器,任何进程(都可以为信号安装自己的自定义处理程序。这样的处理程序可以仔细访问有关段错误上下文的其他信息并将其打印出来,以进行调试或允许您制作错误报告,如您给出的示例所示。

因此,请向维护您修改后的 GCC 编译器的人提交报告。