0
#include <string>
#include <iostream>

void Print(const char* s) {
    std::cout << s << std::endl;
}

std::string GetString() {
    std::string ret;
    ret = "Is this defined behavior?";
    return ret;
}

int main() {
    Print(GetString().c_str());
}

This code seems to work reliably on the big 3 compilers. I'm concerned that it might not actually be defined behavior, is it possible the string could be destroyed leaving the c_str() returned pointer dangling before the Print function is called?

https://godbolt.org/z/cKddvd1aP

273K
  • 29,503
  • 10
  • 41
  • 64
David Carpenter
  • 1,389
  • 2
  • 16
  • 29
  • 4
    The temporary returned by `GetString` will be alive long enough for `Print` to finish with the pointer to the temporary's data. Looks good to me. – user4581301 Aug 23 '23 at 23:40
  • 3
    Handy compiler option: `-fsanitize=address,undefined` Turns on a bunch of extra runtime checks. Doesn't get everything, but it gets a lot of cases where the scope ended too soon. – user4581301 Aug 23 '23 at 23:43
  • 3
    Reliable documentation on the lifetime guarantees: https://en.cppreference.com/w/cpp/language/lifetime#Temporary_object_lifetime – user4581301 Aug 23 '23 at 23:47
  • 3
    And the relevant standard sections: https://eel.is/c++draft/class.temporary and https://eel.is/c++draft/intro.execution#5 – user4581301 Aug 23 '23 at 23:57
  • A noob mistake `return ret.c_str();` would be UB. This isn't. – Swift - Friday Pie Aug 24 '23 at 02:49

1 Answers1

4

This is perfectly well-defined behavior. GetString() returns a temporary std::string, which will be destroyed at the end of the full expression in which it was created. That means it is destroyed on the ; after Print() exits, thus the c_str() pointer will not be dangling inside of Print().

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770