mardi 5 septembre 2023

std::vector emplace_back in emplace_back call UB or bug clang/gcc?

I had a bug in a code who try to emplace back some value when emplacing back in the same vector.

Minimal example

#include <iostream>
#include <vector>


struct ComplexObject
{
    // for display only
    inline static int cpt {};
    int indice {};

    ComplexObject(std::vector<ComplexObject>& storage, int trick) 
    {

        indice = cpt;
        cpt++;

        if (trick == 0 )
        {
            std::cout << "Creating single Object. Storage size: " << storage.size() << std::endl;
        }
        else
        {
            std::cout << "Creating double Object. Storage size: " << storage.size() << std::endl;
            storage.emplace_back(storage, 0);
            std::cout << "Storage size after double creation : " << storage.size() << std::endl;
        }

    }
    
};


int main() {
   std::vector<ComplexObject> storage;
    storage.reserve(3); // no realoction

    storage.emplace_back(storage,0);
    std::cout << "_________ size after insert simple : " << storage.size()<<"_________" << std::endl;
    storage.emplace_back(storage,1);
    std::cout << "_________ size after insert double :" << storage.size() << std::endl;

    for (auto& e : storage)
    {
       std::cout << e.indice;
    }

}

I expected the result for the last loop to be something like 012 or 021

Clang and Gcc get different result:

Clang Demo. Output :

Creating single Object. Storage size: 0
_________ size after insert simple : 1_________
Creating double Object. Storage size: 1
Creating single Object. Storage size: 1
Storage size after double creation : 2
_________ size after insert double :2
02

Gcc Demo. Output :

Creating single Object. Storage size: 0
_________ size after insert simple : 1_________
Creating double Object. Storage size: 1
Creating single Object. Storage size: 1
Storage size after double creation : 2
_________ size after insert double :3
020

Both seem add the element 1 then override it with the element 2 but they disagree on the size of the vector (I think the last 0 in gcc is garbage memory)

Question

This code feel bad, but I wasn't able to find in https://en.cppreference.com/w/cpp/container/vector/emplace_back anything telling me I shouldn't do this.

Is this code UB?

  • If yes, which part?
  • If not, which compiler is wrong? (clang make more sense for me)

Aucun commentaire:

Enregistrer un commentaire