greg7mdp/sparsepp

Compile error in debug mode

lczech opened this issue · 11 comments

Hi there,

sparsepp works perfectly fine when compiled in release mode (with an amazingly small memory footprint, thanks!), but doesn't compile with my debug setup.

The error message comes from the debug version of my STL implementation:

/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/debug/array:86:52: 
error: too many arguments to function call, expected single argument '__other', have 2 arguments
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/debug/array:86:52: error: too many arguments to function call, expected single argument '__other', have 2 arguments
      noexcept(noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>())))
                        ~~~~                       ^~~~~~~~~~~~~~~~~~~~

/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/debug/array:264:23: note: in instantiation of exception specification for 'swap' requested here
    noexcept(noexcept(__one.swap(__two)))
                      ^

/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/bits/stl_pair.h:195:25: note: in instantiation of exception specification for 'swap<unsigned int, 5>' requested here
      noexcept(noexcept(swap(first, __p.first))
                        ^

/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/bits/stl_pair.h:255:23: note: in instantiation of exception specification for 'swap' requested here
    noexcept(noexcept(__x.swap(__y)))
                      ^

/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/bits/stl_algobase.h:148:7: note: in instantiation of exception specification for 'swap<std::__debug::array<unsigned int, 5>, unsigned long>'
      requested here
      swap(*__a, *__b);
      ^

/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/bits/stl_algo.h:1351:10: note: in instantiation of function template specialization 'std::iter_swap<std::pair<std::__debug::array<unsigned
      int, 5>, unsigned long> *, std::pair<std::__debug::array<unsigned int, 5>, unsigned long> *>' requested here
                  std::iter_swap(__p, __q);
                       ^

/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/bits/stl_algo.h:1419:12: note: (skipping 7 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
      std::__rotate(__first, __middle, __last,
           ^

[...]/sparsepp/sparsepp/spp.h:2744:26: note: in instantiation of member function 'spp::sparse_hashtable<std::pair<const std::__debug::array<unsigned int, 5>, unsigned long>,
      std::__debug::array<unsigned int, 5>, spp::spp_hash<std::__debug::array<unsigned int, 5> >, spp::sparse_hash_map<std::__debug::array<unsigned int, 5>, unsigned long,
      spp::spp_hash<std::__debug::array<unsigned int, 5> >, std::equal_to<std::__debug::array<unsigned int, 5> >, spp::libc_allocator<std::pair<const std::__debug::array<unsigned int, 5>, unsigned long> >
      >::SelectKey, spp::sparse_hash_map<std::__debug::array<unsigned int, 5>, unsigned long, spp::spp_hash<std::__debug::array<unsigned int, 5> >, std::equal_to<std::__debug::array<unsigned int, 5> >,
      spp::libc_allocator<std::pair<const std::__debug::array<unsigned int, 5>, unsigned long> > >::SetKey, std::equal_to<std::__debug::array<unsigned int, 5> >, spp::libc_allocator<std::pair<const
      std::__debug::array<unsigned int, 5>, unsigned long> > >::sparse_hashtable' requested here
        sparse_hashtable tmp(MoveDontCopy, *this, resize_to);
                         ^

[...]/sparsepp/sparsepp/spp.h:3276:21: note: in instantiation of member function 'spp::sparse_hashtable<std::pair<const std::__debug::array<unsigned int, 5>, unsigned long>,
      std::__debug::array<unsigned int, 5>, spp::spp_hash<std::__debug::array<unsigned int, 5> >, spp::sparse_hash_map<std::__debug::array<unsigned int, 5>, unsigned long,
      spp::spp_hash<std::__debug::array<unsigned int, 5> >, std::equal_to<std::__debug::array<unsigned int, 5> >, spp::libc_allocator<std::pair<const std::__debug::array<unsigned int, 5>, unsigned long> >
      >::SelectKey, spp::sparse_hash_map<std::__debug::array<unsigned int, 5>, unsigned long, spp::spp_hash<std::__debug::array<unsigned int, 5> >, std::equal_to<std::__debug::array<unsigned int, 5> >,
      spp::libc_allocator<std::pair<const std::__debug::array<unsigned int, 5>, unsigned long> > >::SetKey, std::equal_to<std::__debug::array<unsigned int, 5> >, spp::libc_allocator<std::pair<const
      std::__debug::array<unsigned int, 5>, unsigned long> > >::_resize_delta' requested here
                if (_resize_delta(1))
                    ^

[...]/sparsepp/sparsepp/spp.h:3797:29: note: in instantiation of function template specialization 'spp::sparse_hashtable<std::pair<const std::__debug::array<unsigned int, 5>, unsigned
      long>, std::__debug::array<unsigned int, 5>, spp::spp_hash<std::__debug::array<unsigned int, 5> >, spp::sparse_hash_map<std::__debug::array<unsigned int, 5>, unsigned long,
      spp::spp_hash<std::__debug::array<unsigned int, 5> >, std::equal_to<std::__debug::array<unsigned int, 5> >, spp::libc_allocator<std::pair<const std::__debug::array<unsigned int, 5>, unsigned long> >
      >::SelectKey, spp::sparse_hash_map<std::__debug::array<unsigned int, 5>, unsigned long, spp::spp_hash<std::__debug::array<unsigned int, 5> >, std::equal_to<std::__debug::array<unsigned int, 5> >,
      spp::libc_allocator<std::pair<const std::__debug::array<unsigned int, 5>, unsigned long> > >::SetKey, std::equal_to<std::__debug::array<unsigned int, 5> >, spp::libc_allocator<std::pair<const
      std::__debug::array<unsigned int, 5>, unsigned long> > >::find_or_insert<spp::sparse_hash_map<std::__debug::array<unsigned int, 5>, unsigned long, spp::spp_hash<std::__debug::array<unsigned int, 5> >,
      std::equal_to<std::__debug::array<unsigned int, 5> >, spp::libc_allocator<std::pair<const std::__debug::array<unsigned int, 5>, unsigned long> > >::DefaultValue>' requested here
        return rep.template find_or_insert<DefaultValue>(key).second;
                            ^

[...]/foo.cpp:326:21: note: in instantiation of member function 'spp::sparse_hash_map<std::__debug::array<unsigned int, 5>, unsigned long,
      spp::spp_hash<std::__debug::array<unsigned int, 5> >, std::equal_to<std::__debug::array<unsigned int, 5> >, spp::libc_allocator<std::pair<const std::__debug::array<unsigned int, 5>, unsigned long> >
      >::operator[]' requested here
                    hashmap[ key ] = value;

My setup: Clang 3.9.1
Debug flags:

-O2 -DDEBUG -g -ggdb3 -D_GLIBCXX_DEBUG

that is, with the checked STL implementation.

Any idea what is going on here?

Thanks a lot!
Lucas

I did some more digging. The problem is the -D_GLIBCXX_DEBUG flag, that is, the checked STL version. When removing this, compilation works. But I'd prefer to keep it.

It would be useful to know what's on line 86 of /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/debug/array.
Even more useful would be the output of the preprocessor (add -save-temps to your flags and look for a .ii file).

Line 86 is already printed in the detail listing of my post ;-)

Here is a bit more context. The problematic line is in the swap function of std::array. It seems to be the noexcept specification that is causing trouble:

void
swap(array& __other)
noexcept(noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>())))
{ std::swap_ranges(begin(), end(), __other.begin()); }

I also got the preprocessor .ii file: chunkify.ii.zip. Unpacked, it is 4MB, because of all the headers. Let me know if you want me to prepare something more light-weight instead.

What is the definition of your sparsepp map or set?

I'm using

spp::sparse_hash_map< typename HashFunction::DigestType, size_t >

where HashFunction::DigestType is

using DigestType = std::array< uint32_t, 5 >;

Interesting! Because of the abstraction of DigestType, I didn't see the connection between my hash key type and the array that is causing the compile error. Is this an issue with the STL implementation, after all? Or am I using sparsepp wrongly?

I don't think the issue is in your code. I think it may be an issue with the checked STL, but not 100% sure. Does the issue occur if you use std::unordered_map instead of spp::sparse_hash_map?

No, using a std::unordered_map compiles fine with the same debug settings.

By the way, if it helps, the only operations that I am doing with the map are:

// Init a map from hashes to chunk IDs.
using ChunkHashMap = spp::sparse_hash_map< typename HashFunction::DigestType, size_t >;
ChunkHashMap hash_to_chunk;

// Check if a hash is in there. If so, use the chunk ID. If not, add it.
auto const hash_it = hash_to_chunk.find( hash_digest );
if( hash_it != hash_to_chunk.end() ) {
    auto const chunk_id = hash_it->second;
    // ...
} else {
    // ...
    hash_to_chunk[ hash_digest ] = chunk_count;
}

(some variable declarations left out for simplicity)

The line that is causing the compile error is the last one, where a new element is added.

I think that the checked STL the code you quoted should have a std:: before the swap() call in the noexcept clause, otherwise it tries to call itsef swap(array& __other) which takes a single __other argument

void
swap(array& __other)
noexcept(noexcept(std::swap(std::declval<_Tp&>(), std::declval<_Tp&>())))
{ std::swap_ranges(begin(), end(), __other.begin()); }```

Yep, that works. With the added std::, my code compiles. I just sent a bug report to the libc++ mailing list, let's see what they say about this.

Thanks! I guess, we can close this issue then.

Short update:

It seems there were two problems involved. One with Clang (http://lists.llvm.org/pipermail/cfe-dev/2018-May/058005.html), and one with the libstdc++ (GCC) STL implementation (http://lists.llvm.org/pipermail/cfe-dev/2018-May/058017.html) - the added std however seems not to be the correct solution. The problem was however solved in libstdc++ a while ago, so I probably just need to update, and find out why Clang uses the GCC STL implementation in my setup...

Anyway, the problem is not due to sparsepp, so all good here ;-)

@lczech thanks a lot for the update!