clang与gcc运行时的区别:用clang构建的c++类模板在没有复制构造函数的情况下崩溃,用复制构造函数构建的gcc
clang vs gcc run-time difference: c++ class template built w clang crashes w/o copy constructor, built w gcc crashes with copy constructor
如果使用clang(而不是gcc)构建,除非我为TableTypeCarrier
模板类包含一个复制构造函数,否则以下代码会在运行时崩溃吗?如果我包含复制构造函数,为什么在使用gcc构建时会遇到同样的运行时崩溃?
我定义了以下c++类:
class TableTypeCarrierBase {};
template<class T>
class TableTypeCarrier: public TableTypeCarrierBase {
public:
TableTypeCarrier(const T * const p) : m_p(p) {}
#ifdef __clang__
TableTypeCarrier(const TableTypeCarrier<T>& o) : m_p(o.m_p) {}
#endif
const T * Get() const
{
return m_p;
}
private:
const T * const m_p;
};
struct PsiTable {
PsiTable() : m_priv(NULL) { }
template<typename T> void Set(const TableTypeCarrier<T> inT)
{
m_priv = &inT;
}
template<typename T> const T * Get() const
{
return (!m_priv) ? NULL : ((TableTypeCarrier<T>*)m_priv)->Get();
}
private:
const TableTypeCarrierBase *m_priv;
};
您会注意到TableTypeCarrier
类模板的复制构造函数被条件化为只能由clang而不是gcc构建。
在最初编写这段代码时(没有上述条件化的复制构造函数),我只使用gcc来构建和测试它。当我尝试用clang构建它时,构建总是成功的,但在操作这些类的对象时会出现运行时崩溃。
我花了几个月的时间调试它。我不记得是什么路径导致我尝试向TableTypeCarrier
模板类添加复制构造函数,但事实上,这解决了使用clang构建二进制文件的问题。不幸的是,简单地声明这个复制构造函数似乎会导致与最初描述的问题相同的问题,但只有在使用gcc构建时才会出现。
当然,我添加了预编译器指令,以便只有在使用clang构建时才对复制构造函数进行条件化。
这个修复对我有效,但我想了解原因。
如果你需要上下文来完全理解这个问题,这里有一个链接到在历史上这个确切的代码仍然存在的时候在整个项目中定义这些类的标题:
https://github.com/mkrufky/libdvbtee/blob/v0.4.0/libdvbtee/decode/table/table.h
此后,我重构了代码,并删除了TableTypeCarrierBase
类和TableTypeCarrier
模板类,因为它们是不必要的代理。尽管删除了这些代码,但我仍然想理解为什么当TableTypeCarrier
有(或没有)复制构造函数时,用clang构建的二进制文件与用gcc构建的二进制代码的行为不同。
为什么clang构建的二进制文件需要这个复制构造函数?如果我包含gcc构建的二进制文件,为什么它会崩溃?
我在这里看到一个问题:
template<typename T> void Set(const TableTypeCarrier<T> inT)
{
m_priv = &inT;
}
您通过值传递参数(并因此生成它的副本),但随后您获取它的地址并将其分配给成员变量。当函数结束时,您获取地址的对象将消失,留下一个悬空指针。
处于适当高警告级别的编译器应该对此进行标记。
- CMake:将文件从构建目录复制到源直接
- 如何在构建时改进我的脚本和复制程序资源?
- CMake:如何根据配置和架构复制不同的文件来构建目录
- 通过make_shared防止复制构建
- 我的lambda在复制构建期间没有正确转换捕获的"this"
- 如何在 Visual Studio 2015 中的构建结束时复制文件
- 复制C DLL以构建任何C#项目的输出,以扩展为参考
- UNORDERED_MAP的存在确定是否使用了复制构建器或移动构造器
- 将资产目录从源复制到在CMAKE中构建目录
- STD ::复制在调试构建中失败
- 如何在使用 CMake 制作后将目录的内容复制到构建目录中
- C 编译器可以在用户定义和编译器生成的复制构建器之间进行自由选择
- Qmake在构建时复制多个文件
- 将 exe 文件复制到 Qt 构建目录
- 在不复制的情况下构建范围内的向量
- 使用 std::string 参数和不可移动/可复制参数构建 std::map
- 如何将一个项目的构建文件复制到第二个项目的include/library目录
- clang与gcc运行时的区别:用clang构建的c++类模板在没有复制构造函数的情况下崩溃,用复制构造函数构建的gcc
- 如何对CMake构建的不可复制SegFault进行故障排除
- libC++库的地址净化构建为什么会在libcxx类中出现不可复制的ASAN问题