Re: std::string add nullptr attribute

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

 



On Mon, 20 Feb 2023 at 10:26, Xi Ruoyao <xry111@xxxxxxxxxxx> wrote:
>
> On Sun, 2023-02-19 at 21:33 +0000, Jonny Grant wrote:
>
> > I noticed -Wanalyzer-null-dereference reports at build time a
> > dereference. Also works if a function parameter. I wondered why
> > std::string isn't detected by this static analyser option.
>
> Because the analyzer does not know the C++ standard disallows to use
> NULL here.  It just analyzes the code.  The code in libstdc++ reads:
>
>       basic_string(const _CharT* __s, const _Alloc& __a = _Alloc())
>       : _M_dataplus(_M_local_data(), __a)
>       {
>         // NB: Not required, but considered best practice.
>         if (__s == 0)
>           std::__throw_logic_error(__N("basic_string: "
>                                        "construction from null is not valid"));
>         const _CharT* __end = __s + traits_type::length(__s);
>         _M_construct(__s, __end, forward_iterator_tag());
>       }
>
> As you can see yourself, though the standard implies using NULL here is
> a UB, libstdc++ does not really code a UB here.  So the analyzer will
> consider the code absolutely valid.

Right, it's defined behaviour in libstdc++, as an extension.

>
> Note that throwing a C++ exception is not a programming error.  It's
> perfectly legal to catch the exception elsewhere.  It's also perfectly
> legal not to catch it and treat it as an abort() (calling abort is also
> not a programming error).
>
>
> > It's not pretty, but this wrapper catches NULL passed at compile time:
> >
> > std::string make_std_string(const char * const str)
> > {
> >     // This line ensures: warning: dereference of NULL '0' [CWE-476]
> > [-Wanalyzer-null-dereference]
> >     char b = *str;
>
> You are invoking an undefined behavior here if str is NULL, so it's
> essentially same as using a nonnull attribute for make_std_string.

And turned defined behaviour back into UB. The warning isn't reliable
(only if the compiler can see the point is null, which isn't the case
without optimization, or if the pointer comes from some non-inline
function), the exception is. You're trading guaranteed exception for a
not guaranteed warning and unbounded misoptimization due to undefined
behaviour.

Even if this was a robust solution, is it really a problem that needs
to be solved?



[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux