1

What am I missing here? This is really irritating!

Essentially, in main() t.p3() ALWAYS produces random garbage as if the pointer is invalid, yet everything else ALWAYS works! I determined that the difference is in the length of the string. What voodoo is this?

How do I get t.p3() to work?

#include <string>
#include <iostream>

static const std::string STRING1( "xxxxxxxxxxxxxxx" );
static const std::string STRING2( "xxxxxxxxxxxxxxxx" ); // MAGIC 16 characters

struct Test
{
    std::string string1() const { return STRING1; }
    std::string string2() const { return STRING2; }
    const char * p1() const { return STRING1.c_str(); }
    const char * p2() const { return STRING2.c_str(); }
    const char * p3() const { return string1().c_str(); }
    const char * p4() const { return string2().c_str(); }

};

int main(int argc, char *argv[])
{
    Test t;
    std::cout << t.p1() << std::endl; // works
    std::cout << t.p2() << std::endl; // works
    std::cout << t.p3() << std::endl; // random garbage
    std::cout << t.p4() << std::endl; // works
    return 0;
}
BuvinJ
  • 10,221
  • 5
  • 83
  • 96
  • 1
    What you're experiencing is undefined behavior. Only `t.p1()` and `t.p2()` truly "work". – Kevin Mar 01 '17 at 21:08
  • 1
    In order to get `p3` and `p4` to work you need to change the return type to `const std::string&` so you still refer to the global strings instead of a copy made by returning by value. – NathanOliver Mar 01 '17 at 21:09
  • I think you're right Nathan! I'll check... – BuvinJ Mar 01 '17 at 21:10
  • 1
    The difference between `p3()` and `p4()` is where the string representation is located: for `p3()` the small string optimisation is probably used putting the characters into the string object itself. That gets overwritten before the string gets printed. For `p4()` the string representation is probably on the heap and probably not overwritten by the time the string is printed. Of course, there is no guarantee either way as the code results in undefined behavior. – Dietmar Kühl Mar 01 '17 at 21:11
  • Nathan's answer works! But, I over simplified my real use case. I would like to return a new std::string under some conditions, and a const default under others. (So can't return a reference to the new one I created with function scope if I change the function signature that way) – BuvinJ Mar 01 '17 at 21:17
  • Since returning a reference worked, I went and created a class member to store my dynamic strings in addition to the constants my function could return. I hate having to do that, but it makes perfect sense. Thanks everyone! – BuvinJ Mar 01 '17 at 22:24

0 Answers0