C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Relocation in C++

From: Edward Catmur <ecatmur_at_[hidden]>
Date: Sun, 22 May 2022 10:46:20 -0600
On Fri, 20 May 2022 at 18:52, Thiago Macieira <thiago_at_[hidden]> wrote:

> I don't think that's sufficient. The change needs to be opt-in, not
> opt-out.
> Otherwise, we're going to have silent breakages because of some libraries
> recompiled and others not.
>

Uh, if a library is not recompiled, then it uses the old ABI, and if it is
recompiled then either it's compiled against old source code, so uses the
old ABI, or is compiled against new source code with relocation operator
defined but also with the opt-out in place, so it uses the old ABI. And if
an old compiler (or a new compiler in an old mode) uses the new source code
then the relocation operator will be #if defined out, so it uses the old
ABI.

All that library authors need to do is to ensure that if/when they enable
relocation by adding a relocation operator to a nontrivial class, they
consider the potential ABI break and add the opt-out if they want to
maintain ABI compatibility.

As far as the language goes, we need to permit implementations to use the
old ABI, and to ensure that ABI is maintained for old source code that is
unaware of the new facility. This is done first of all by suppressing the
relocation operator for types with a user-defined destructor, so that
enabling relocation on nontrivial types becomes an active decision.
Further, nontrivial aggregating/inheriting types (that don't have their own
user-defined destructor, but are not trivially destructible) will need to
be implicitly opted out.

Moreover, it needs to be opt-in per call site, not per type. One library
> declaring a type cannot know where that type gets used: it might be used
> by
> another library in its own ABI. So even if the first library has no ABI
> break,
> another one downstream of it might. As an example of std::unique_ptr,
> currently libc++ has no functions defined in its ABI that take it as a
> parameter:
>
> $ nm -DC --defined /lib64/libc++.so.1 | grep -c ' T .*unique_ptr'
> 0
>
> So if libc++ opted in, it would see no difference in its binary. But the
> next
> level would:
>
> $ nm -DC --defined /lib64/libgpgmepp.so.6 | grep ' T .*unique_ptr'
> 00000000000238e0 T GpgME::Context::startEditing(GpgME::Key const&,
> std::unique_ptr<GpgME::EditInteractor,
> std::default_delete<GpgME::EditInteractor> >, GpgME::Data&)
> [...]
>
> Without any markers, this would cause a resource leak.


If the mechanism is opt-out per type, then libc++ will opt out
std::unique_ptr in the standard Library headers, and both GpgME and its
callers will know to use the old (nontrivial) ABI for that parameter. So no
leak, and no double-free.

It's pretty clear there
> would be a marker somewhere, like the __attribute__((abi_tag)), which
> means
> this wouldn't be a silent breakage, but it would still be a break. This is
> exactly what happened to std::string in libstdc++, when it went from
> std::basic_string<...> to std::__cxx11::basic_string<...>.
>
> The problem with opt-in, of course, is that too few people will remember
> to
> opt in.
>

Well, people will have to opt-in anyway; nontrivial classes will not get
trivial relocation without a source addition (i.e., defaulting the
relocation operator), since the compiler doesn't know which classes are
safe to trivially relocate. The opt out is to gain the benefit of
relocation for container internals (vector resize, etc.) while preserving
ABI.

But a further criterion is rule-of-zero: classes that do not define special
member functions (destroy, move, copy) should not need to do anything to
gain the benefit of relocation. So those classes should not need to either
opt in or opt out, but this should happen automatically.

Received on 2022-05-22 16:46:32