在类模板上使用arm gcc进行编译时出现段错误

时间:2018-06-19 21:07:02

标签: c++ templates gcc

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

使用基于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文件中)

Main.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.

2 个答案:

答案 0 :(得分:1)

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

使用C ++ 11,可以在类定义中初始化类成员。通过将此功能与struct数组一起使用来触发编译器segfault,该struct数组的大小是从模板参数得出的:

pair buffer_[filterLen_] = {};

AFAIK,从C ++ 11开始,此表达式应使用空的初始化程序列表对类成员数组进行聚合初始化。这等效于通过一个空列表{}初始化每个数组元素,该列表对各个结构执行聚合初始化(再次使用一个空的初始化列表)。

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

答案 1 :(得分:0)

不是您的代码导致分段错误,而是您的编译器捕获了自己的分段错误,并给了您更多信息。

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

Segmentation fault (core dumped)
当进程退出时,

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

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