1

Given this code, would that be undefined behaviour?

struct S {
  void foo() {
    // non-static member function, but not using "this"
  }
};

int main() {
  S* s = new S;
  std::thread t(std::bind(&S::foo, s));
  delete s;
}

Point here being: "this" is not used at all inside foo(), but it is a normal member function. Am I allowed to destroy the instance although another thread is still running on it?

(I know that for all practical purposes, this would not crash. But is it undefined behaviour?)

And second: what if foo() uses member variables, but I guarantee (via locking, events or whatever) that it won't access anything from "this" from the time onwards the instance is deleted?

  • 2
    Why is `S::foo` non-static if it has no use for `this` ? – WhozCraig Nov 14 '19 at 11:52
  • 2
    `what if foo() uses member variables` then it _is_ actually using `this` – Zaffy Nov 14 '19 at 11:54
  • 4
    There is no guarantee that the thread enters `foo` before `delete s;` is executed. If the thread start is delayed then `s->foo();` is UB as it is dereferencing a deleted pointer. – Richard Critten Nov 14 '19 at 12:06
  • @RichardCritten You have a point. Deleted my answer. – eike Nov 14 '19 at 12:12
  • 2
    This should answer your question: https://stackoverflow.com/a/49213482/4253931 – eike Nov 14 '19 at 12:13
  • 1
    "I know that for all practical purposes, this would not crash." I think more important is that for all practical purpose you shouldnt be writing code like this. non-static member functions do use `this`, if they dont they should be static or not a member in the first place – 463035818_is_not_an_ai Nov 14 '19 at 12:13
  • There's no place in the standard that explicitly spells out all the things you aren't allowed to do with objects whose lifetimes have ended. There is http://eel.is/c++draft/basic.memobj#basic.life-6 which unambiguously says that you can't call non-static member functions on a "not-yet" or "not-anymore" object, but it doesn't technically apply to your question because that paragraph is only for when you already/still have storage. But it should be obvious that it doesn't become _less_ UB by also not having the storage. – Max Langhof Nov 14 '19 at 12:30
  • (That is, if we assume the `delete` happens before the member function call in your code, which is the contentious case that you presumably want to know about. That may or may not happen depending on how the race condition in your code plays out, but I'm not 100% sure if the race itself is UB.) – Max Langhof Nov 14 '19 at 12:35

0 Answers0