C++ Logo

std-discussion

Advanced search

Re: Passing member functions to a thread in the face of relocations - is this standard C++11?

From: David Carter <dch888_at_[hidden]>
Date: Sat, 13 Aug 2022 09:57:13 +0100
The standard seems to be entirely silent about passing pointers of objects
on the stack vs heap. There must be literally hundreds of situations in
the standard where a warning triangle should be placed. I'm wondering how
this could be fixed. Maybe there could be a contract or pragma which would
disallow pointers to objects on the stack to be passed into another
function. Has this been raised before?

I've fixed this by putting the class containing the thread pool on the heap
(i.e. ClassName above). Subtle!

Thank you,
David.

On Fri, 12 Aug 2022 at 17:24, David Carter <dch888_at_[hidden]> wrote:

> Dear C++ Standards People,
>
> I just wanted to check a situation with you, about what the various
> standards say, if anything, about a threading situation I've come across
> recently.
>
> - C++11 with VC14
> - Using std::threads in a threadpool type application.
> - Works perfectly within GoogleTest but when loaded from a DLL in a
> application, it hangs.
>
> Debugged it and the fact is that the 'this' pointer changes in between
> times when the threads are created and when the main loop is running. The
> this pointer that the threads have end up pointing to garbage (so it's not
> a stale copy of the class). If I query the this pointer value in the main
> thread it is different to the one the threads have. I think the class
> instance has been relocated in memory. Nothing in my code is copying the
> class - it is effectively a singleton.
>
> It's something like this:
>
> for (size_t i=0; i < numThreads; ++) {
> threadPool_.push_back(std::thread(&ClassName::ClassFn, this, arg1,
> arg2, arg3));
> }
> . . .
> queue work
> . . .
> condition_variable stuff
>
> threadPool_ is a private member of ClassName and of type
> std::vector<std::thread>
>
> I checked the C+11 standard Section 30 and I didn't see this situation
> covered - in fact the work relocation doesn't seem to appear in the
> document at all. Maybe I'm barking up the wrong tree here. From what I've
> gathered the constructor to std::thread can take a std::invoke pattern
> which I believe I'm following above. However in a lot of examples I can
> find the instance variable passed in is a stack variable not this, perhaps
> this is special? Also std::invoke is C++17 and beyond so that's maybe not
> applicable to C++11's std::thread?
>
> Hopefully I'm doing something dumb and this can be fixed with a reference
> wrapper or somehting like this. I can ask a wider audience about this
> situation but I wanted to check in with someone who knows the threading
> standards to check that I haven't made a silly mistake first. The fact
> that it compiles cleanly and runs ok without relocations in a test harness
> gives me encouragement that the code is OK.
>
> I know the standard can't cover all the implementation details, and it's
> always possible to write pathological code which will always break, but
> something like this seems pretty fundamental, providing I'm not breaking
> the standard here?
>
> Thank you,
> David.
>
> --
> Mathematics, Modelling, C/C++, Python, Linux, SQL, MATLAB, Mathematica.
> LinkedIn Profile: https://www.linkedin.com/in/david-carter-a259671a4/
>
>
>

-- 
Mathematics, Modelling, C/C++, Python, Linux, SQL, MATLAB, Mathematica.
LinkedIn Profile:  https://www.linkedin.com/in/david-carter-a259671a4/

Received on 2022-08-13 08:57:25