C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Derived class's function invokes base class's function

From: Thiago Macieira <thiago_at_[hidden]>
Date: Sat, 16 Apr 2022 11:28:17 -0700
On Saturday, 16 April 2022 06:22:41 PDT Frederick Virchanza Gotham via Std-
Proposals wrote:
> // I'm using a union here
> // because g++ gives a
> // compiler error for
> // reinterpret_cast
> union {
> void (*f)(void);
> bool (Base::*m)(void);
> } const fm = { _method };

Because you're not supposed to do this.

Your code is UB and WILL FAIL on some architectures or with some objects
because you failed to set up the other half of the PMF properly.

The original IA-64 C++ ABI used the lowest bit on the first pointer-word to
denote whether the PMF referred to a virtual function or not, because on
Itanium all functions are aligned to 16 bytes, so the 3 low bits were free.
When it got ported to x86, that restriction remained, as x86 doesn't have an
alignment restriction, so it was easy to ask the compiler to align all member
functions. That's why your code seems to work on x86: any valid function
pointer is a valid entry point for a PMF.

But on 32-bit ARM with Thumb Interwork, the low bit isn't free, so the psABI
uses the high word to indicate whether it's virtual or not. Your code did not
initialise the high word at all.

Either way, your code will likely crash in release mode for the same reason:
you failed to initialise the this-adjustment portion of the PMF. That means
the compiler is adding garbage to the this pointer when it places the PMF-
mediated call on the next line:

> return (p->*fm.m)();

You've been lucky so far because you're calling functions that don't need
access to member data in the this object and aren't placing virtual calls of
their own. Or the high word in that PMF happened to be zeroed.

-- 
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel DPG Cloud Engineering

Received on 2022-04-16 18:28:19