Ryan Feeley
Ryan Feeley

Reputation: 667

Segfault during compilation with arm gcc on class template

I have a class template that implements a median filter. The template parameters are the data type and the filter length.

I'm getting a segfault when compiling with arm-none-eabi-g++, which is based on gcc 4.8.3. The code compiles without warning with either Clang 5.0.1 or Gcc 7.3.0.

I'm compiling for c++11.

Is the problem with my code, or truly a gcc bug? If a bug, is there a convenient work around? Even if not a bug, I'd appreciate any recommendations for improvements.

Things I can think of that might be the cause (although I think they should both be permissible):

Code

Declaration

// 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_};

};

Definitions (in .h file) Not Shown

Main.cpp

#include <cstdint>
using std::uint16_t;

#include "MedianFilter.h"

int main() {
    MedianFilter<uint16_t, 7> filt;
    filt.update(0);
    return 0;
}

Error Output:

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.

Upvotes: 1

Views: 1449

Answers (2)

Ryan Feeley
Ryan Feeley

Reputation: 667

At described in @einpoklum's answer, this is a compiler bug that was fixed in gcc 4.9.1. The workaround is rather trivial -- omit the brace initialization of the array of struct and achieve your design intent some other way. For example, you can provide default member initializers in the struct's definition.

With C++11, class members can be initialized within the class definition. The compiler segfault was triggered by using this feature with an array of struct where the array size was derived from a template parameter:

pair buffer_[filterLen_] = {};

AFAIK, starting with C++11, this expression should do aggregate initialization of the class member array with an empty initializer list. This is equivalent to initializing each array element by an empty list {}, which performs aggregate initialization (again with an empty initializer list) on the individual structs.

For one reason or another, this syntax causes the compiler to segfault. The workaround with gcc prior to 4.9.1 is simply to avoid this syntax.

Upvotes: 2

einpoklum
einpoklum

Reputation: 132128

It's not your code that causes a segmentation fault, it's your compiler which caught its own segmentation fault and gave you a more informative error.

Usually when a process performs a segmentation fault, i.e. tries to access a memory segment in an unauthorized fashion, the default signal handler is called, and what you see is something like:

Segmentation fault (core dumped)

printed to the standard error stream as the process exits. But a process (not just your compiler, any process) can install its own custom handlers for signals. Such a handler can access - carefully - additional information regarding the context of the segfault and print it out, for debugging or for allowing you to make an error report, as in the example you gave.

So, please submit a report to whoever maintains your modified GCC compiler.

Upvotes: 0

Related Questions