5

Both these calls to get_string and get_string2 return objects which go out of scope when the function returns. Shouldn't the returned object be an address in memory which goes out of scope after the function returns? This is using Visual Studio 2008. Should this always work? Why?

#include <iostream>

enum myID { SMALL, MEDIUM, LARGE };

const char* get_string(myID id) {
   switch(id){
      case SMALL: return "small";
      case MEDIUM: return "medium";
      case LARGE: return "large";
      default: return "unknown";
   }
}

const char* get_string2(myID id) {
   char* s = 0;
   switch(id){
      case SMALL:  s = "small"; return s;
      case MEDIUM: s = "medium"; return s;
      case LARGE:  s = "large"; return s;
      default: return "unknown";
   }
}

int main() {
   std::cout << get_string(SMALL) << std::endl;
   std::cout << get_string2(SMALL) << std::endl;
   return 0;
}
Angus Comber
  • 9,316
  • 14
  • 59
  • 107
  • possible duplicate of [returning a pointer to a literal (or constant) character array (string)?](http://stackoverflow.com/questions/4836534/returning-a-pointer-to-a-literal-or-constant-character-array-string) – Mark B May 16 '13 at 15:44

2 Answers2

12

String literals are the only literals that are lvalues and have static storage duration. So returning a pointer to the first element of a string literal is very safe. Compare

const char* f1()
{
      return "Hello"; // OK
} 

const char* f2()
{
      const char s[6] = "Hello";
      return s; // Undefined Behavior
} 


const char* f3()
{
      const char* s = "Hello";
      return s; //OK
} 

Judging from comments, this answer needs some elaboration. OK, see, a string literal is stored in the memory until the program has finished. In case 1 you return a pointer to it. The object pointer to is alive, so it's fine. In case 3, you take the address of the literal into a local variable s and return the latter by copy. The copy of the address still points to a valid memory, so it's fine. In the second case, however, we copy the string literal into a local array s which is destroyed upon function exit. Returning the address of a local variable is undefined behavior.

Further, if what you thought was undefined behavior were actually undefined then you shouldn't be surprised either because undefined behavior can mean

  • doesn't work
  • works sometimes
  • always works
  • does funny inexplicable stuff
  • anything

So if something works it doesn't mean it's OK. In this case it is, but not in the general case.

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • So because it is a string literal it is not stored as a stack variable? It is stored in a global variable? Do you have a web link with details of this? – Angus Comber May 16 '13 at 15:37
  • would you mind to explain a bit further on the undefined behavior case? I just like to know – mr5 May 16 '13 at 15:37
  • Just a nit (because the effect is the same), but in `f2`, you don't copy anything (officially, at least). It's exactly as if you'd written `char const s[6] = { 'H', 'e', 'l', 'l', '0', '\0' };`. – James Kanze May 16 '13 at 15:53
  • @JamesKanze: You are of course right, since it is initialization, but I think it is easier to understand it this way. At least in this question. – Armen Tsirunyan May 16 '13 at 15:56
  • now I think I need to go back again study the difference of an array and a pointer – mr5 May 16 '13 at 16:07
  • @mr5: It is indeed unfortunate that a lot of C++ "books" do not put enough, if any, emphasis on the difference. Please refer to [a good book](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list), such as that by S.Lippman. – Armen Tsirunyan May 16 '13 at 16:16
  • What is the string literals are allocated in the data section of a *.dll(*.so) that gets unloaded. I think that would cause undefined behavior also – Ghita May 16 '13 at 18:42
4

This memory does not go out of the scope. These are string literals, they exist all time while the program runs.

nullptr
  • 11,008
  • 1
  • 23
  • 18