我有一个实现中值过滤器的类模板。模板参数是数据类型和过滤器长度。
使用基于gcc 4.8.3的arm-none-eabi-g ++进行编译时遇到段错误。使用Clang 5.0.1或Gcc 7.3.0编译代码时不会发出警告。
我正在为c ++ 11进行编译。
我的代码是问题还是真正的gcc错误?如果有错误,是否有方便的解决方法?即使不是错误,也希望有任何改进建议。
我能想到的可能是原因(尽管我认为它们都应允许):
// 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_};
};
#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.
答案 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编译器的人提交报告。