0

I have a container such as this:

std::unordered_set<char*, Hash, Equal> my_set;

I want to free the char*'s inside this container before I .clear() it, so I do,

for(auto i : my_set){
    free(i);
}
my_set.clear();

But this means, before the .clear(), the container is corrupted. I am inclined to think that this is normal, given that I am going to clear it anyway. But I should know if this is undefined behavior, or can it be used ?

Max Paython
  • 1,595
  • 2
  • 13
  • 25
  • 3
    Did you allocate the memory with `malloc`? It's very rare to use it in C++. – molbdnilo Jan 25 '22 at 07:10
  • 3
    What do you mean by "corrupted"? That shouldn't be able to modify the container itself in any way. – molbdnilo Jan 25 '22 at 07:11
  • @molbdnilo I used `malloc` of course. My use cases include some rare situations unfortunately. And I am not modifying the container by it's methods. But free'ing the member pointers of this container, makes it impossible to rehash / compare etc.. I am asking if this is undefined behavior. – Max Paython Jan 25 '22 at 07:24
  • Why such a strange construction?.. C++ language has the RAII idiom which helps to manage resources. In any way, you may use the `std::shared_ptr` instead of the `char*`. Because you can easily get the memory leakage and/or segmentation faults with `std::unordered_set`. – Serge Roussak Jan 25 '22 at 07:25
  • @SergeRoussak You are most probably right, however I am handling the memory management myself. And trying to find out if this (however uncommon), can be done. – Max Paython Jan 25 '22 at 07:28
  • OK, you are free to choose your way. But, there is the `Allocator` template parameter which allows to adjust this moments. Probably, you may play with it. – Serge Roussak Jan 25 '22 at 07:34
  • By the way, [here](http://cpp.sh/8plkr) is a live demo. – Serge Roussak Jan 25 '22 at 07:35
  • 1
    If you're asking about the point *between* freeing the pointers and the clearing, then yes, at that point you have a container full of dangling pointers and all the normal rules about what's undefined apply. But you don't do anything there, so... – molbdnilo Jan 25 '22 at 08:15
  • A data structure that contains an invalid pointer is not much different from the invalid pointer itself. You should be extra careful when touching either, and it is best to get rid of either ASAP as they become invalid. – n. m. could be an AI Jan 25 '22 at 08:40

1 Answers1

1

But this means, before the .clear(), the container is corrupted.

The container is not corrupted. It stores char*s, which can be thought of as numerical addresses at which text might be stored. If valid text is no longer stored at those addresses, that's perfectly fine as long as no attempt is made to follow/dereference the pointer to access that memory. unordered_map<char*> treats the char* as values/numbers and is effectively unaware that they might point at anything - it will never dereference the pointers even if the container was resized/rehashed. And anyway, the container will never resize unless you do more insertions that cross the max_load_factor().

What it does mean is that you've - momentarily - got a container full of dangling pointers. That's not undefined behaviour - it's perfectly fine, the same way that this is fine:

{
    char* p = strdup("boo");
    free(p);
}

There, p is a dangling pointer after the free(), but nothing nasty happens as the scope exists - there is no hidden/implicit destructor to run for char* objects.

That said, it would be better to use RAII semantics - a type wrapping the char* that will free it in the destructor: this answer shows one way to do that with std::unique_ptr.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252