vendredi 30 novembre 2018

UBSan complains when calling a member of a derived class from a lambda within a thread

I stumbled upon this issue, where UBSan complains about calling a member function of a derived class through a supposedly invalid pointer - yet I am unable to see why it should be invalid.

I have broken down my code to the following snippet, which you can also examine here in a live version.

struct Base {
    virtual ~Base() {
        for(auto& t : ts) {
            t.join();
        }
    }

    template<typename F>
    void Spawn(F&& f) {
        ts.emplace_back(std::forward<F>(f));
    }

    std::vector<std::thread> ts;
};

struct Foo : public Base {
    Foo() { }

    void Start() {
        Spawn([this] { Member(); /* HERE */ });
    }

    void Member() { }
};

int main() {
    Foo f;
    f.Start();
}

Basically, what I am doing is the following:

  • Create a lambda, which captures the this pointer of the current derived class Foo
  • Spawn a thread which is stored in the respective base class Base
  • Call the lambda from the thread
  • Call a member function from the lambda

UBSan complains as soon as a member of Foo is accessed by the captured pointer within the lambda (output from the live example):

prog.cc:31:52: runtime error: member call on address 0x7ffc50687018 which does not point to an object of type 'Foo'
0x7ffc50687018: note: object is of type 'Base'
 00 00 00 00  48 b5 44 00 00 00 00 00  e0 c6 ce 01 00 00 00 00  e8 c6 ce 01 00 00 00 00  e8 c6 ce 01
              ^~~~~~~~~~~~~~~~~~~~~~~
              vptr for 'Base'

What am I missing here?

Aucun commentaire:

Enregistrer un commentaire