gpt4 book ai didi

C++ 11 GCC 4快速优化不在堆栈中存储抽象类的实现类

转载 作者:行者123 更新时间:2023-12-02 10:28:45 25 4
gpt4 key购买 nike

所以伙计们,我有一个抽象类,另一个类将这个类的实现存储在堆栈中(我不想要堆分配,而且我不知道在不让调用者显式声明实现的情况下其他方法)和另一个存储此接口(interface)类的引用。但是,GCC似乎没有将实现类存储在堆栈中,并且在使用接口(interface)类时可能找不到实现类vtable。
基本上,在没有优化的情况下使用 GCC 4.8.1 编译时一切正常,但是当我尝试使用它时,程序崩溃然后返回 139。
我不知道为什么 GCC 4 不支持它,而 GCC 5 支持,但我看到它们生成不同的指令。
编译器资源管理器: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;
}

最佳答案

正如其中一条评论所说,存储 TCustom 时发生了一些奇怪的事情。在不相关的类型中 RCustom .隐式构造函数RCustom(TCustom)把我扔了。
这个问题相当微妙。如果某些东西适用于 -O0 但不适用于 -Ofast(或 -O2/-O3),则大多数时候内存会发生一些有趣的事情。如Benny K说,在你的情况下,问题是 RCustom仅存储对 IFormatter 的引用:

class RCustom {
...
const IFormatter& Formatter; // Asking for problems
}
这似乎是一个无辜的 & ,但实际上这是危险的。因为此成员的有效性取决于外部对象的生命周期。有几种方法可以解决这个问题。您可以保存 TFormatter 的拷贝在 RCustom (而不是引用):
template<typename T>
class RCustom {
...
const TFormatter<T> Formatter;
}
但这也意味着你必须放弃抽象接口(interface) IFormatter对于具体的 TFormatter<T> .要在 C++ 中使用虚方法,您需要一个指针,但使用原始指针将引入与引用相同的内存问题。所以我建议你使用智能指针:
class RCustom {
...
std::shared_ptr<const IFormatter> Formatter;
}
PS:准确地说出了什么问题:在 MakeCustom()你初始化一个 TCustom初始化和复制 TFormatter 实例的对象.接下来是对 TFormatter 实例的引用在 TCustom保存在 RCustom .现在这个 RCustom对象被返回,函数 MakeCustom()被清理。在这个清洗过程中 TCustom被摧毁, TFormatter 也是如此。 -成员。但是 RCustom仍然保留对这个无效内存的引用。在 C++ 中, & 之间的区别没有 &比较重要。

关于C++ 11 GCC 4快速优化不在堆栈中存储抽象类的实现类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63169853/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com