• Is this safe?

    From boltar@boltar@caprica.universe to comp.lang.c++ on Sat Jul 18 09:19:35 2026
    From Newsgroup: comp.lang.c++

    Is this function thread safe? Ie will the return string value be set on
    the stack before the lock_guard is released?

    string mygetter(void)
    {
    lock_guard<mutex> lock(setmtx);
    return some_string_set_elsewhere;
    }

    or do I need to do this:

    string mygetter(void)
    {
    lock_guard<mutex> lock(setmtx);
    string tmp = some_string_set_elsewhere;
    return tmp;
    }

    I should probably know the answer to this but I'm not 100% sure.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Paavo Helde@eesnimi@osa.pri.ee to comp.lang.c++ on Sat Jul 18 17:58:16 2026
    From Newsgroup: comp.lang.c++

    On 7/18/2026 12:19 PM, boltar@caprica.universe wrote:
    Is this function thread safe? Ie will the return string value be set on
    the stack before the lock_guard is released?

    string mygetter(void)
    {
    lock_guard<mutex> lock(setmtx);
    return some_string_set_elsewhere;
    }

    or do I need to do this:

    string mygetter(void)
    {
    lock_guard<mutex> lock(setmtx);
    string tmp = some_string_set_elsewhere;
    return tmp;
    }

    I should probably know the answer to this but I'm not 100% sure.


    AFAIK these are functionally equivalent and the compiler can optimize
    them to the same machine code. To my knowledge, both are safe (the
    return value is constructed before destroying local variables like lock).


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From boltar@boltar@caprica.universe to comp.lang.c++ on Sat Jul 18 15:25:14 2026
    From Newsgroup: comp.lang.c++

    On Sat, 18 Jul 2026 17:58:16 +0300
    Paavo Helde <eesnimi@osa.pri.ee> gabbled:
    On 7/18/2026 12:19 PM, boltar@caprica.universe wrote:
    Is this function thread safe? Ie will the return string value be set on
    the stack before the lock_guard is released?

    string mygetter(void)
    {
    lock_guard<mutex> lock(setmtx);
    return some_string_set_elsewhere;
    }

    or do I need to do this:

    string mygetter(void)
    {
    lock_guard<mutex> lock(setmtx);
    string tmp = some_string_set_elsewhere;
    return tmp;
    }

    I should probably know the answer to this but I'm not 100% sure.


    AFAIK these are functionally equivalent and the compiler can optimize
    them to the same machine code. To my knowledge, both are safe (the
    return value is constructed before destroying local variables like lock).


    Thanks. That is certainly the sensible approach but you can never be 100%
    sure with C++.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c++ on Sat Jul 18 17:12:47 2026
    From Newsgroup: comp.lang.c++

    On 7/18/2026 2:19 AM, boltar@caprica.universe wrote:
    Is this function thread safe? Ie will the return string value be set on
    the stack before the lock_guard is released?

    string mygetter(void)
    {
    lock_guard<mutex> lock(setmtx);
    return some_string_set_elsewhere;
    }


    That's okay. But I totally understand why you would ask.



    or do I need to do this:

    string mygetter(void)
    {
    lock_guard<mutex> lock(setmtx);
    string tmp = some_string_set_elsewhere;
    return tmp;
    }

    I should probably know the answer to this but I'm not 100% sure.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c++ on Sat Jul 18 17:26:45 2026
    From Newsgroup: comp.lang.c++

    On 7/18/2026 8:25 AM, boltar@caprica.universe wrote:
    On Sat, 18 Jul 2026 17:58:16 +0300
    Paavo Helde <eesnimi@osa.pri.ee> gabbled:
    On 7/18/2026 12:19 PM, boltar@caprica.universe wrote:
    Is this function thread safe? Ie will the return string value be set on
    the stack before the lock_guard is released?

    string mygetter(void)
    {
    -a-a-a-alock_guard<mutex> lock(setmtx);
    -a-a-a-areturn some_string_set_elsewhere;
    }

    or do I need to do this:

    string mygetter(void)
    {
    -a-a-a-alock_guard<mutex> lock(setmtx);
    -a-a-a-astring tmp = some_string_set_elsewhere;
    -a-a-a-areturn tmp;
    }

    I should probably know the answer to this but I'm not 100% sure.


    AFAIK these are functionally equivalent and the compiler can optimize
    them to the same machine code. To my knowledge, both are safe (the
    return value is constructed before destroying local variables like lock).


    Thanks. That is certainly the sensible approach but you can never be 100% sure with C++.


    You can see it in action by making a raii object cout what its doing. Something like this:

    _____________________
    #include <iostream>

    struct raii
    {
    raii()
    {
    std::cout << "(" << this << ")->raii::raii()\n";
    }

    ~raii()
    {
    std::cout << "(" << this << ")->raii::~raii()\n";
    }
    };


    struct raii_return
    {
    int m_state = 0;

    raii_return(int state) : m_state(state)
    {
    std::cout << "(" << this << ")->raii_return::raii_return()
    m_state = " << m_state << "\n";
    }

    ~raii_return()
    {
    std::cout << "(" << this << ")->raii_return::~raii_return()
    m_state = " << m_state << "\n";
    }
    };


    raii_return
    foo()
    {
    raii raii0;

    std::cout << "foo()\n";

    return raii_return(42);
    }


    int main()
    {
    std::cout << "before foo()\n";
    foo();
    std::cout << "after foo()\n";

    return 0;
    }
    _____________________


    Gives me this output, examine it:
    _____________________
    before foo()
    (0x7fffd424560f)->raii::raii()
    foo()
    (0x7fffd424563c)->raii_return::raii_return() m_state = 42 (0x7fffd424560f)->raii::~raii()
    (0x7fffd424563c)->raii_return::~raii_return() m_state = 42
    after foo()
    _____________________


    It works fine.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Fred. Zwarts@F.Zwarts@HetNet.nl to comp.lang.c++ on Sun Jul 19 12:07:01 2026
    From Newsgroup: comp.lang.c++

    Op 18.jul.2026 om 11:19 schreef boltar@caprica.universe:
    Is this function thread safe? Ie will the return string value be set on
    the stack before the lock_guard is released?

    string mygetter(void)
    {
    lock_guard<mutex> lock(setmtx);
    return some_string_set_elsewhere;
    }

    or do I need to do this:

    string mygetter(void)
    {
    lock_guard<mutex> lock(setmtx);
    string tmp = some_string_set_elsewhere;
    return tmp;
    }

    I should probably know the answer to this but I'm not 100% sure.


    These two are equivalent. If string is std::string, then it is safe.
    I was once caught by a similar construction, but where string was a C
    string, i.e. a pointer to an array of char.
    Then only a pointer to the array was returned. Another thread could
    damage the contents of the array before the caller could read it.
    In that case the work around in the second function would not help.
    Instead of creating a new pointer, a pointer to a copy of the array must
    be returned.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From boltar@boltar@battlestar-galactica.com to comp.lang.c++ on Sun Jul 19 18:46:13 2026
    From Newsgroup: comp.lang.c++

    On Sun, 19 Jul 2026 12:07:01 +0200
    "Fred. Zwarts" <F.Zwarts@HetNet.nl> wrote:
    Op 18.jul.2026 om 11:19 schreef boltar@caprica.universe:
    I should probably know the answer to this but I'm not 100% sure.


    These two are equivalent. If string is std::string, then it is safe.
    I was once caught by a similar construction, but where string was a C >string, i.e. a pointer to an array of char.
    Then only a pointer to the array was returned. Another thread could
    damage the contents of the array before the caller could read it.
    In that case the work around in the second function would not help.
    Instead of creating a new pointer, a pointer to a copy of the array must
    be returned.

    Returning raw char* from a C function can lead to all sorts of gotchas in the higher level code. The classic one is calling the a function that returns a pointer to a static buffer 2 or more times in a printf, eg inet_ntoa().
    Then there's strtok().....

    --- Synchronet 3.22a-Linux NewsLink 1.2