UBSan жалуется при вызове члена производного класса из лямбды в потоке - PullRequest
0 голосов
/ 30 ноября 2018

Я наткнулся на эту проблему, когда UBSan жалуется на вызов функции-члена производного класса через предположительно недействительный указатель - но я не могу понять, почему он должен быть недействительным.

Я сломал свойкод для следующего фрагмента, который вы также можете изучить здесь в реальной версии .

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();
}

По сути, я делаю следующее:

  • Создайте лямбду, которая захватывает this указатель текущего производного класса Foo
  • Создает поток, который хранится в соответствующем базовом классе Base
  • Вызовите лямбду изпоток
  • Вызов функции-члена из лямбды

UBSan жалуется, как только к члену Foo обращается захваченный указатель в лямбда-выражении (вывод из живого примера):

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'

Что мне здесь не хватает?

...