在小对象优化中调试崩溃以进行类型擦除
Debugging crash in small object optimization for type erasure
我正在实现一个对小对象执行类型擦除的类,并且遇到了我不理解的分段错误。
以下程序:
#include <iostream>
#include <type_traits>
struct small_object
{
public:
template<class T>
small_object(const T& value)
{
new(&storage_) concrete<T>(value);
}
~small_object()
{
get_abstract().~abstract();
}
void print() const
{
// XXX crash here
get_abstract().print();
}
private:
struct abstract
{
virtual ~abstract(){}
virtual void print() const = 0;
};
template<class T>
struct concrete
{
concrete(const T& value) : value_(value) {}
void print() const
{
std::cout << value_ << std::endl;
}
T value_;
};
abstract& get_abstract()
{
return *reinterpret_cast<abstract*>(&storage_);
}
const abstract& get_abstract() const
{
return *reinterpret_cast<const abstract*>(&storage_);
}
typename std::aligned_storage<4 * sizeof(void*)> storage_;
};
int main()
{
small_object object(13);
// XXX i expect this line to print '13' to the terminal but it crashes
object.print();
return 0;
}
在 XXX
指示的行处崩溃。
我相信问题是对.print()
的虚拟调用没有被正确动态调度,但我不明白为什么。
谁能说出我错过了什么?
您没有从abstract
派生concrete<T>
,因此当您使用放置new
构造对象时,不会创建 vtable。因此,当您尝试调用虚拟函数时,它将失败; 在此示例中,concrete<T>
和 abstract
实际上是完全不相关的类型。
如果您使用的是 C++11 或更高版本,我建议您使用 override
关键字,以允许编译器在这种情况下生成错误。
std::aligned_storage<4 * sizeof(void*)> storage_;
这将创建一个字节的存储。
template 参数不设置声明对象的大小,而是设置可在适当大小的此类数组中分配的对象的大小。因此,您需要
std::aligned_storage<4 * sizeof(void*)> storage_[4 * sizeof(void*)];
GCC 6.2.0 会就此发出警告:
警告:placement new
在类型为 'std::aligned_storage<32ul>
' 且大小为 '1
' 的区域中构造类型为 '
small_object::concrete<int>
' 且大小为 '16
' 的对象 [-Wplacement-new=]
(您仍然需要从abstract
派生concrete
)。
相关文章:
- 在运行时处理类型擦除的数据-如何不重新发明轮子
- 类型擦除的std::function与虚拟函数调用的开销
- 如何在C++中允许成员函数的自定义返回类型进行类型擦除?
- 如何投射类型擦除的 std::function?
- 类型擦除代码的依赖注入单元测试
- 标准库中是否有与 std::thread 的构造函数语义匹配的类型擦除函数包装器?
- 类型擦除和一种模板方法模式
- 在小对象优化中调试崩溃以进行类型擦除
- 带有模板复制和移动构造函数的C++类型擦除
- C++技术:类型擦除与纯多态性
- 使用类型擦除创建运行时type_traits查询
- 类型擦除是否有效取决于优化级别
- 转换为类型擦除的元组
- 如何实现像 std::function 这样的自毁类型擦除类
- unique_ptr类型擦除析构函数不能正常工作(带有警告)
- 什么是C++中的类型擦除
- C++类型擦除,请使用 std::function 捕获单个类的多个方法
- Boost类型擦除的实践和发现
- 现代C++中的类型擦除分配器
- c++类型擦除/类型封装?发现类型