entt: Duplicate storage for the same component

I’ve been running into the problem that some components went “missing”. After investigating I noticed at some point a second storage for the same type is being created.

I used following code for outputting info (trying with different namespaces and without typedef)

      TRACE << " E        " << (Uint32)e.entity();
      TRACE << " R        " << e.registry();
      TRACE << " S        " << &e.registry()->storage<::Children>();
      TRACE << " S (size) " << e.registry()->storage<::Children>().size();
      TRACE << " T1       " << entt::type_id<::Children>().hash();
      TRACE << " T2       " << entt::type_id<std::vector<entt::entity>>().hash();

I was able to get two different outputs right after creating the entity

 E        418
 R        0x55a490312658
 S        0x55a490341680
 S (size) 3
 T1       2301207559
 T2       2301207559
 E        418
 R        0x55a490312658
 S        0x55a4903d5e90 // different storage
 S (size) 0
 T1       2301207559
 T2       2301207559

There now seems be be a new storage for the type Children.

When printing out all storages with

for (auto [n, s] : e.registry()->storage())
{
    TRACE << s.type().name() << " : " << &s << (entt::type_id<::Children>().hash() == n ? " <<<<" : "");
}

I get following output (❗ this is from a different run so the pointers are different from above):

std::vector<entt::entity> : 0x55e27bf4cbe0 <<<<
[...]
std::vector<entt::entity> : 0x55e27bd9eb30

Things to note

  • I started to notice it only in release mode
  • This might have started suddenly without any code change regarding this entity (but I’m not sure)
  • Happens in code that is part of the same executable (not between shared libs or anything like that)
  • I’ve noticed this even in the same compilation unit!
  • Hard to reproduce. Slight changes in code affect this behaviour.
  • compiler is gcc 13.2.1 20230801
  • entt version 3.12.2

I suspect it has something to do with hashes being created differently, since in the output above only one of the strorages hash matches. But I’m a bit at a loss here on how to proceed 😅

About this issue

  • Original URL
  • State: closed
  • Created 10 months ago
  • Comments: 41 (18 by maintainers)

Commits related to this issue

Most upvoted comments

Fair enough but how do we make the issue searchable? I mean, it’s so already and it contains lot of words that match with the right keywords. How can we improve this eventually?

Could it be that at some point in the code the compiler is unable to see the whole type declaration, making it skip the allocator... part?

I just did some additional testing. In the code I gave you, there are two calls to emplace<Children> one in main and one in Create(). If you add the following right after each call to emplace<Children>

    std::cout << "Calling  emplace<Children>()" << std::endl;
    constexpr auto stripped = entt::internal::stripped_type_name<Children>();
    constexpr auto value = entt::hashed_string::value(stripped.data(), stripped.size());
    std::cout << "   Stripped name :" << stripped << std::endl;
    std::cout << "   hashed   name :" << value << std::endl;

This is the output I got when running with GCC11.4+Release+Ubuntu22.04

In Create
Calling  emplace<Children>()
   Stripped name :std::vector<entt::entity, std::allocator<entt::entity> >
   hashed   name :2361607097
2361607097 : std::vector<entt::entity>
In Main
Calling  emplace<Children>()
   Stripped name :std::vector<entt::entity>
   hashed   name :2301207559
2361607097 : std::vector<entt::entity>
2301207559 : std::vector<entt::entity>
Error detected!!! 2361607097 vs 2301207559
Ok! 2301207559 == 2301207559
  • It looks like the stripped_name is different on each of the different calls resulting in a different hash being calculated

  • This seems to be happening when the two emplace< > are in different compilation units. Moving the Create() function to main.cpp causes it to work again and results in the following:

In Create
Calling  emplace<Children>()
   Stripped name :std::vector<entt::entity>
   hashed   name :2301207559
2301207559 : std::vector<entt::entity>
In Main
Calling  emplace<Children>()
   Stripped name :std::vector<entt::entity>
   hashed   name :2301207559
2301207559 : std::vector<entt::entity>
Ok! 2301207559 == 2301207559

I personally would not use using to specify a component type. You could use class Children : public std::vector<entt::entity> {} or similar to create a new type.

I don’t want to create a new type. I was just using a typedef for convenience. The issue persists regardless of using the typedef or std::vector<entt::entity> directly.