bug-gnucap
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Segment fault at exit when compiled with Clang and libc++


From: LdBeth
Subject: Re: Segment fault at exit when compiled with Clang and libc++
Date: Thu, 01 Feb 2024 09:40:58 -0600
User-agent: Wanderlust/2.15.9 (Almost Unreal) SEMI-EPG/1.14.7 (Harue) FLIM-LB/1.14.9 (Gojō) APEL-LB/10.8 EasyPG/1.0.0 Emacs/29.1 (x86_64-apple-darwin20.6.0) MULE/6.0 (HANACHIRUSATO)

>>>>> In <tencent_C1D1B9070B234867D04AE4AFC28DA91BC605@qq.com> 
>>>>>   LdBeth <andpuke@foxmail.com> wrote:
>>>>> In <tencent_59FCFE0CDC28BA531DE77AE0304E748AAC09@qq.com> 
>>>>>   LdBeth <andpuke@foxmail.com> 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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]