Re: Segment fault at exit when compiled with Clang and libc++
LdBeth <[email protected]> Thu, 01 Feb 2024 09:40:58 -0600
| Newsgroups | gmane.comp.gnu.gnucap.bugs |
|---|---|
| Message-ID | <[email protected]> |
>>>>> In <[email protected]> >>>>> LdBeth <[email protected]> wrote: >>>>> In <[email protected]> >>>>> LdBeth <[email protected]> wrote: ldb> Compiling the library with debug info can gives the backtrace. ldb> Actually, there are two places cause the segfault. Their backtraces ldb> leads to C++ std::less(), but I don't found that very helpful, so ldb> I tried my best to isolate the problem. ldb> I found the cause is this method in `l_indirect.h` ldb> size_t erase(void* b, void* e) { ldb> size_t c=0; ldb> assert(b <= e); ldb> for (void* i=b; i<=e; i=reinterpret_cast<bool*>(i)+1) { ldb> c += _map.erase(i); ldb> } ldb> return c; ldb> } I spend this morning to exclude the possibility that segfault was generate by pointer casting and seems I found the exact cause: So _map is defined in the same file as std::map<const void*, T> _map; And the segfault is indeed generated inside the libc++ std::less() template, because that is called map.erase() by to compare keys, but unfortunately by some template initialization process I don't understand, std::less is initialized to std::less<void const*>, which isn't something specified by C++ standard I guess. The difference between libc++ and GNU libstdc++ is pictured in an article https://quuxplusone.github.io/blog/2019/01/20/std-less-nightmare/ (Although the problem in the article is not fully related to this bug, it shows libstdc++ casts pointer to uintptr_t to compare, which looks like to be the non standard behavior that was depend on. ldb> (lldb) target create "./gnucap-modelgen" ldb> Current executable set to '/Users/ldbeth/Downloads/gnucap-20240130-dev/modelgen/O/gnucap-modelgen' (x86_64). ldb> (lldb) run ldb> Process 12511 launched: '/Users/ldbeth/Downloads/gnucap-20240130-dev/modelgen/O/gnucap-modelgen' (x86_64) ldb> Process 12511 stopped ldb> * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x2c) ldb> frame #0: 0x0000000100384cbc libgnucap.dylib`CKT_BASE::~CKT_BASE() [inlined] std::__1::less<void const*>::operator(this=<unavailable>, __x=<unavailable>, __y=0x000000000000002c)(void const* const&, void const* const&) const at operations.h:487:21 [opt] ldb> 484 #endif ldb> 485 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY ldb> 486 bool operator()(const _Tp& __x, const _Tp& __y) const -> 487 {return __x < __y;} ldb> 488 }; ldb> 489 ldb> 490 #if _LIBCPP_STD_VER > 11 ldb> Target 0: (gnucap-modelgen) stopped. ldb> warning: libgnucap.dylib was compiled with optimization - stepping may behave oddly; variables may not be available. So the obvious fix to me is define the proper pointer comparing when define the map, although the exact compare function should be used is unknown to me because I don't understand what the INDIRECT template class is trying to do. --- ldbeth