【问题标题】:gcc 4.7.3 internal compiler error when using make_shared with a constructor将 make_shared 与构造函数一起使用时的 gcc 4.7.3 内部编译器错误
【发布时间】:2013-11-29 02:57:14
【问题描述】:

我知道问题出在哪里,我只是不确定为什么我没有从 gcc 得到任何错误输出。

产生问题的有问题的行是:

std::string type,rel,pred;
std::tie( type, rel, pred ) = tuple;
auto supertype = std::make_shared<Node>( Token( type ) ); // This
auto predicate = std::make_shared<Node>( Token( pred ) ); // and this

仅供参考,Node Ctor 是:

Node ( Token & token )

如果我这样做,我不会收到任何错误:

auto type_token = Token( type );
auto pred_token = Token( pred );
auto supertype = std::make_shared<Node>( type_token );
auto predicate = std::make_shared<Node>( pred_token );

我的 GCC 是:

posix gcc 版本 4.7.3 (Debian 4.7.3-8)

实际错误是:

> Internal compiler error: Error reporting routines re-entered. Please
> submit a full bug report, with preprocessed source if appropriate. See
> <file:///usr/share/doc/gcc-4.7/README.Bugs> for instructions.

有趣的是,上面的这个目录甚至都不存在。

在 make_shared 构造函数中构造对象有什么问题?

【问题讨论】:

    标签: c++ gcc c++11 constructor shared-ptr


    【解决方案1】:

    临时对象不能绑定到非const 左值引用。因此,您不能将 1 传递给指定的 Node 构造函数。编译器应该拒绝:

    Node node1(Token(type));
    Node node2(Token(pred));
    

    尝试让std::make_shared 使用您的代码在内部执行相同的初始化也是如此:

    auto supertype = std::make_shared<Node>( Token( type ) );
    auto predicate = std::make_shared<Node>( Token( pred ) );
    

    您正试图让make_shared 将该临时对象传递给非const 左值构造函数。编译器应该将程序诊断为格式错误并且无法编译它。这显然与 ICE 崩溃不同,后者总是表明存在编译器错误。

    解决方法是按照您在“但这确实有效”代码中的建议进行操作 - 将左值引用传递给 make_shared - 或为 Node 编写右值引用构造函数:

    Node(Token&&);
    

    编辑:我认为这是GCC bug# 56869,它似乎已在 4.6.4 和 4.7.4 中修复,并于 2013 年 11 月 18 日关闭。如果有人阅读本文可以轻松地在 4.7.4 中运行此测试用例:

    #include <memory>
    #include <string>
    
    struct Token {
      Token(std::string lex);
    };
    
    struct Node {
      Node(Token& token);
    };
    
    int main() {
        auto supertype = std::make_shared<Node>(Token{"foo"});
        auto predicate = std::make_shared<Node>(Token{"bar"});
    }
    

    请在评论中发布结果。

    【讨论】:

    • 回答问题。出于好奇,this^^ 适用于临时对象,但 not 堆分配的对象,例如std::make_shared( new Token( foo ) ),假设构造函数将接受一个指针。 coliru.stacked-crooked.com/a/f94c856dd5f3800b
    • GCC 4.8 可以正确编译这个程序,spewing a ton of error messages.
    • @Alex 右值是正确的,它可以是临时值、函数返回值以及std::move(...) 在左值上的结果。一个指针就可以了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-22
    • 2014-05-16
    • 1970-01-01
    相关资源
    最近更新 更多