[squid-dev] [PATCH] Deletors for std::unique_ptr WAS: Re: Broken trunk after r14735

Alex Rousskov rousskov at measurement-factory.com
Fri Jul 29 18:29:48 UTC 2016


On 07/29/2016 09:27 AM, Amos Jeffries wrote:
>>> typedef std::unique_ptr<BIO, std::function<decltype(BIO_free)>> BIO_Pointer;

> I got this config parsing crash replicated here and tried a dozen or so
> combinations. It does seem to keep coming back to my earlier approach of
> using per-type Functors as the most reliable solution.

AFAICT, this is not a question of reliability, and we should not be
fixing this by trying various combination of typedef characters until we
find one that does not immediately crash Squid. We should figure out
_why_ trunk code does not work (and then fix it accordingly).

The trunk code cannot work because we are telling std::unique_ptr that
our Deleter is std::function<decltype(BIO_free)>. What is
std::function<decltype(BIO_free)>? It is an std::function class. An
instance of that class can call any function that has the same
declaration as BIO_free. So, which function should our BIO_Pointer call?
We did not specify that! Thus, we get a bad_function_call exception when
unique_ptr object is trying to destroy its target pointer [using a
missing/unspecified deleter function].

In other words, trunk code is equivalent to this pseudo code:

  BIO *bio = ...;
  std::function<int(BIO*)> fun = NULL;
  fun(bio); // throws -- cannot call an unspecified function

What we should be writing is this:

  BIO *bio = ...;
  std::function<int(BIO*)> fun = BIO_free;
  fun(bio); // frees bio

Since std::function supports default construction, the "= NULL" part is
implicit -- we do not need to pass NULL to std::unique for the default
std::function constructor to construct an empty/non-callable functor.


> We could also wrap the std::unique_ptr definition parts inside the macro
> for much smaller visible code. But that would prevent re-use of the
> macro for other plain Functor definitions (not that anything else is
> using it).

If possible, we should avoid macros and should learn how to use C++11
correctly. In general, it makes little sense to suffer the pains of
switching to C++11 and then use macros for things C++11 is supposed to
provide or support natively.

However, in this specific case, some macros may be unavoidable or even a
good idea because we are also dealing with C libraries that we cannot
convert to C++11. Please give me a few hours to think whether there is a
macro-free solution available.


Thank you,

Alex.



More information about the squid-dev mailing list