代码之家  ›  专栏  ›  技术社区  ›  for_stack

编译器对初始值设定项列表赋值的优化使程序核心转储?

c++
  •  1
  • for_stack  · 技术社区  · 5 年前

    如果我不打开任何编译器优化,下面的代码可以正常工作。但是,如果我用优化方法编译它,它将核心转储,也就是说。 -O2

    string key = "hi";
    auto il = {"get", key.c_str(), "ha"};
    
    printf("%p\n", *(il.begin() + 1));   // the address of the second element is normal.
    
    for (const auto &ele : il)
        cout << ele << endl;      // output is normal.
    
    il = {"get", key.c_str()};    // <-- assignment
    
    printf("%p\n", *(il.begin() + 1));  // now, the address is ABNORMAL!!!
    
    for (const auto &ele : il)
        cout << ele << endl;     // <-- output is ABNORMAL.
    

    编译器似乎优化了对初始值设定项列表的赋值,并使其无效。我用多个测试代码 CLANG GCC 版本,它具有相同的行为。

    我的问题是:

    1. 分配初始值设定项列表有效吗?
    2. 如果它是有效的,编译器会怎么做使赋值打破初始值设定项列表?

    更新 :

    即使我不放弃引用 il.begin ,即评论 printf("%p\n", *(il.begin() + 1)); ,分配初始值设定项列表后,无法正确输出。所以打电话是无效的 il = {"get", key.c_str()}; ?

    1 回复  |  直到 5 年前
        1
  •  5
  •   Holt    5 年前

    你的代码 未定义行为 因为你试图取消引用 il.begin() 不再有效:

    类型的对象 initializer_­list<E> 提供对类型为的对象数组的访问 const E . [艾斯] 注: 一对指针或一个指针加上一个长度将是 initializer_­list . 初始值设定项列表 用于实现在中指定的初始值设定项列表 [dcl.init.list] . 复制初始值设定项列表不会复制基础元素。 阿格斯 期末笔记 埃斯·阿

    分配一个 initializer_list ,但为了访问元素,原始 初始值设定项列表 必须仍然存在,例如:

    auto il1 = {1, 2, 3};
    std::initializer_list<int> il2;
    il2 = il1; // ok because il1 still exists
    

    在你的情况下, {"get", key.c_str()} 是临时的,因此其生存期在以下语句之后结束:

    il = {"get", key.c_str()};
    

    访问 开始() 有效,但取消引用是ub。