jeudi 30 juillet 2020

C++11 GCC 4 Fast Optimization don't store implementation class from abstract class in the stack

So guys, I have an abstract class, other class that stores an implementation from this class in the stack (I don't want heap allocations and I don't know other way to do it without making the caller explicitly declares the implementation) and another that stores a reference of this interface class. But, it seems that GCC don't store the implementation class in the stack and when the interface class is used probably the implementation class vtable is not found.

Basically, everything works fine when compiled with GCC 4.8.1 without optimizations, but when I try to use it, the program crashes and then returns 139.

I don't know why GCC 4 doesn't support it, while GCC 5 does, but I see that they generate different instructions.

Compiler Explorer: https://godbolt.org/z/Wfvj65

#include <cstdio>

#define FORCEINLINE inline __attribute__((always_inline))

class IFormatter
{
public:
    virtual void Format(const void* InData) const = 0;
};

template<typename T>
class TFormatter :
    public IFormatter
{
public:
    TFormatter() = delete;
};

using Scalar = float;

// Implemented, fine.
struct RVector2
{
    Scalar X;
    Scalar Y;
};

// Not implemented, get error.
struct RVector3
{
    Scalar X;
    Scalar Y;
    Scalar Z;
};

template<>
class TFormatter<RVector2> :
    public IFormatter
{
public:
    virtual void Format(const void*) const override
    {
        printf("[RVector2]\n");
    }
};

template<typename T>
class TCustom
{
public:
    FORCEINLINE TCustom(const T& InValue) :
        Value(InValue),
        Format(TFormatter<T>{})
    {
    }

    FORCEINLINE const T* Data() const
    {
        return &Value;
    }

    FORCEINLINE const IFormatter& Formatter() const
    {
        return Format;
    }

private:
    const T& Value;
    TFormatter<T> Format;
};

template<typename T>
FORCEINLINE TCustom<T> MakeCustom(const T& InValue)
{
    return TCustom<T>{ InValue };
}

class RCustom
{
public:
    FORCEINLINE RCustom(const void* InValue, const IFormatter& InFormatter) :
        Data(InValue),
        Formatter(InFormatter)
    {
    }

    template<typename T>
    FORCEINLINE RCustom(TCustom<T> const& InCustom) :
        RCustom(InCustom.Data(), InCustom.Formatter())
    {
    }

    FORCEINLINE const IFormatter& Get() const
    {
        return Formatter;
    }

private:
    const void* Data;
    const IFormatter& Formatter;
};

int main()
{
    const RVector2 Vector{};
    const RCustom Custom = MakeCustom(Vector);
    Custom.Get().Format(nullptr);
    
    return 0;
}

Aucun commentaire:

Enregistrer un commentaire