G++-11 销毁顺序从 G++9 更改

如何解决G++-11 销毁顺序从 G++9 更改

我们有以下代码(它比较复杂,我试着做一个最小的例子)。

#include <iostream>
#include <vector>
#include <string>
#include <memory>

template<typename T>
struct use_type
{
    use_type(T& v) : value(v) {}
    T& value;
};

template<typename T>
use_type<T> use(T& value) { return use_type<T>(value); }

template<typename T>
use_type<T> use(const T& value) { return use_type<T>(const_cast<T&>(value)); }

template<typename T>
struct printer_helper
{
    void use(const use_type<T>& use) { uses.push_back(use); }
    void final_action()
    {
        for (const auto& use : uses)
        {
            std::cout << use.value.size() << std::endl;
            for (const auto& v : use.value)
            {
                std::cout << v << ",";
            }
            std::cout << std::endl;
        }
    }
    std::vector<use_type<T>> uses;
};

template<typename T>                                        
struct printer
{
    printer() { helper = new printer_helper<T>(); }
    printer<T>& operator,(const use_type<T>& t)
    {
        helper->use(t);
        return *this;
    }
    ~printer()
    {
        helper->final_action();
        delete helper;
    }
    printer(const printer&) = delete;
    printer& operator =(const printer&) = delete;
    printer(printer&&) = default;
    printer& operator =(printer&&) = default;
    printer_helper<T>* helper;
};

template<typename T>
struct printer_creator
{
    printer<T> operator << (const char*) { return {}; }
};

int main()
{
    using vec = std::vector<std::string>;
    {
    /*vec v1{"abc","bcd"};
    vec v2{"new","old","real"};*/
    printer_creator<vec> p;
    p << "",use(vec{"abc","bcd"}),use(vec{"new","real"});
    //p << p,use(v1),use(v2);
    }
}

代码在 g++-11 之前的 g++ 上运行良好。使用 g++-11,它在输出中要么是段错误要么是垃圾。是UB吗?如果是的话,也许您可​​以告诉我,哪些 gcc 更改使其失败并在可能的情况下引用标准?

现场示例:

g++-10 g++-11

解决方法

临时向量在创建它们的行的末尾被破坏。 p 在其作用域的末尾(即向量之后)被破坏。由于 p 的析构函数使用对现在悬空的向量的引用,因此您的代码具有未定义的行为。

如果它曾经奏效,那纯粹是“运气”,向量析构函数使向量处于可用状态。

,

p << "",use(vec{"abc","bcd"}),use(vec{"new","old","real"});

您创建了 3 个临时对象

  • printer<vec> 来自 p << "")
  • vec{"abc","bcd"}
  • vec{"new","real"}

它们之间没有顺序(见下面的注释),所以它们可以按任何顺序创建。

只有从左到右的破坏是正确的(所以从右到左的构造),其他顺序将使用悬空引用并且是UB。而且由于您没有订单保证...

注意:
我们通过重载 operator &&/operator ||,
失去短路 我们通过重载 operator,

失去了从左到右的评估顺序

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?