Consider this simple program:
#include <string>
#include <sparsehash/dense_hash_map>
int main()
{
google::dense_hash_map<std::string, int> map;
map["foo"] = 0;
}
Compiling with GCC 8.2 and -Wclass-memaccess
(or -Wall
) produces a warning:
sparsehash/internal/libc_allocator_with_realloc.h:68:40: warning:
‘void* realloc(void*, size_t)’ moving an object of non-trivially copyable type
‘struct std::pair<const std::__cxx11::basic_string<char>, int>’;
use ‘new’ and ‘delete’ instead [-Wclass-memaccess]
return static_cast<pointer>(realloc(p, n * sizeof(value_type)));
~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
The questions are:
I've filed an issue here: https://github.com/sparsehash/sparsehash/issues/149
Yes, it is undefined behavior.
But don't despair yet, iff std::string
doesn't store any internal pointers in your implementation, nor registers them anywhere, it will "work" anyway; making a bitwise copy will be equivalent to move-construction at the destination and destructing the source.
Such is the case for most (not all) string-implementations, SSO or not.
If you might use a type not guaranteed to be trivially destructively-moveable, use a different allocator (last template-argument) to avoid bitwise-moves.
Making a program blow up due to invalid moveing by bitwise copy is trivial.
Use this type with google::dense_hash_map
:
class bang {
bang* p;
public:
bang() : p(this) {}
bang(bang const&) : bang() {}
bang& operator=(bang const&) { return *this; }
~bang() { if (p != this) std::abort(); }
};