std::to_address allows temporary "fancy pointers" which will return a dangling pointer

1,587 views
Skip to first unread message

Nathan Oliver

unread,
Mar 28, 2019, 10:53:04 AM3/28/19
to ISO C++ Standard - Discussion
Currently std::to_address is declared as

template<class Ptr>
   
auto to_address(const Ptr& p) noexcept;
 
template<class T>
   
constexpr T* to_address(T* p) noexcept;

and if you use it like

auto bad = to_address(std::make_unique<Foo>());

You will be left with a dangling pointer since the temporary object gets destroyed.  

Is this the intended behavior?  If not this can be easily solved by adding another overload of

template<class Ptr>
   
auto to_address(const Ptr&& p) = delete;

So the function can't be called with a temporary object.

Thank you,
Nathan Oliver

Nicolas Lesser

unread,
Mar 28, 2019, 11:25:25 AM3/28/19
to Nathan Oliver, ISO C++ Standard - Discussion
> --
>
> ---
> You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to std-discussio...@isocpp.org.
> To post to this group, send email to std-dis...@isocpp.org.
> Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.

I don't know whether this is intended but it seems like this another one of those unfortunate results (don't know how else to call it). If you pass in a temporary std::shared_ptr it is possibly valid, so I don't think we should restrict to_address. You might have other custom smart pointers where it's also valid.

It's like std::string_view: `std::string_view a = get_str();` (where get_str() returns std::string) should really be ill-formed, but then you can't do this (`foo` takes a std::string_view): `foo(get_str());`, which is perfectly valid. :(

Nicol Bolas

unread,
Mar 29, 2019, 10:45:20 AM3/29/19
to ISO C++ Standard - Discussion
But we want to be able to call it with a temporary object. Such as in:

auto ptr = to_address(some_vector.begin());

The ContiguousIterator-to-pointer version of `to_address` wasn't quite added to C++20, but it's still a thing we want/need. And it needs to be able to take temporaries.

inkwizyt...@gmail.com

unread,
Mar 29, 2019, 3:32:22 PM3/29/19
to ISO C++ Standard - Discussion, nathanol...@gmail.com



On Thursday, March 28, 2019 at 4:25:25 PM UTC+1, Nicolas Lesser wrote:
Nathan Oliver wrote:
> Currently std::to_address is declared as
>
> template<class Ptr>
>     auto to_address(const Ptr& p) noexcept;
>   template<class T>
>     constexpr T* to_address(T* p) noexcept;
>
>
> and if you use it like
>
> auto bad = to_address(std::make_unique<Foo>());
>
> You will be left with a dangling pointer since the temporary object gets
> destroyed.  
>
> Is this the intended behavior?  If not this can be easily solved by adding
> another overload of
>
> template<class Ptr>
>     auto to_address(const Ptr&& p) = delete;
>
>
> So the function can't be called with a temporary object.
>
> Thank you,
> Nathan Oliver
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to std-dis...@isocpp.org.
> To post to this group, send email to std-dis...@isocpp.org.
> Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.

I don't know whether this is intended but it seems like this another one of those unfortunate results (don't know how else to call it). If you pass in a temporary std::shared_ptr it is possibly valid, so I don't think we should restrict to_address. You might have other custom smart pointers where it's also valid.

It's like std::string_view: `std::string_view a = get_str();` (where get_str() returns std::string) should really be ill-formed, but then you can't do this (`foo` takes a std::string_view): `foo(get_str());`, which is perfectly valid. :(


Isn't shared have same problem as unique? You can have last shared pointer as value, and then it will deallocate when expression ends. Even if it was not last, you have no guarantees that someone else will delete this pointer at any time.

Nicolas Lesser

unread,
Mar 30, 2019, 6:47:21 AM3/30/19
to inkwizyt...@gmail.com, ISO C++ Standard - Discussion, nathanol...@gmail.com
> > an email to std-dis...@isocpp.org <javascript:>.
> > > To post to this group, send email to std-dis...@isocpp.org <javascript:>.
> >
> > > Visit this group at
> > https://groups.google.com/a/isocpp.org/group/std-discussion/.
> >
> > I don't know whether this is intended but it seems like this another one
> > of those unfortunate results (don't know how else to call it). If you pass
> > in a temporary std::shared_ptr it is possibly valid, so I don't think we
> > should restrict to_address. You might have other custom smart pointers
> > where it's also valid.
> >
> > It's like std::string_view: `std::string_view a = get_str();` (where
> > get_str() returns std::string) should really be ill-formed, but then you
> > can't do this (`foo` takes a std::string_view): `foo(get_str());`, which is
> > perfectly valid. :(
> >
>
>
> Isn't shared have same problem as unique? You can have last shared pointer
> as value, and then it will deallocate when expression ends. Even if it was
> not last, you have no guarantees that someone else will delete this pointer
> at any time.

That's why I said "possibly". You're right of course :)

--
- Nicolas
Reply all
Reply to author
Forward
0 new messages