5

I'm writing a user API, is it right to return a const char* value this way?

const char * returnErrorString(int errorCode)
{
   switch(errorCode)
    ...
   return "This error code means that...";
}

I don't like returning string literals this way but they shouldn't be destroyed before being read by the user due to RVO optimizations, is this correct? Any suggestion on that?

Marco A.
  • 43,032
  • 26
  • 132
  • 246

3 Answers3

6

It's OK.

String literal has a fixed address during program's life. You can pass its address as pointers to everywhere. String literals will not destroy while the program is alive.

Just try not to modify them which invokes undefined behavior. Per § 2.14.5 : "The effect of attempting to modify a string literal is undefined."

masoud
  • 55,379
  • 16
  • 141
  • 208
3

String literals are const; they're put up in the read-only data segment (GCC puts it in .rodata section); some implementations store them in the text/code segment, which too is read-only. This is one of the reasons it's illegal to modify a string literal this way.

 char *literal = "You can't edit me!";   // compiler will flag it as a warning for missing const
 literal[0] = 'U';

Don't worry about its destruction; it will live as long as the process/application which uses your library/API is active.

Community
  • 1
  • 1
legends2k
  • 31,634
  • 25
  • 118
  • 222
  • @JanHudec No, he doesn't, but what segments mean (and whether segments exist at all) depends on the implementation. Some implementations use "code segment" for both code and read-only data, and "data segment" for modifiable data. –  Oct 03 '13 at 07:42
  • The terms "data segment" and "code segment" are confusing here, because they can mean different things depending on context and implementation. Proper name for the place where dynamic allocations go is "heap". Proper name for the part where the non-zero static data go is probably "data _section_" (which is distinct from the "text section" containing actual code). – Jan Hudec Oct 03 '13 at 07:46
  • @legends2k: Quoting from the link: "The string literal will be allocated in **data** segment." (emphasis mine). Than it goes on to link to [this article](http://en.wikipedia.org/wiki/Data_segment), which defines "data segment" = "data (section) + bss (section) + heap". – Jan Hudec Oct 03 '13 at 07:49
  • Still it is the most commonly used scenario such as in gcc/++ so above wordings helps to make it generic. +1 – fkl Oct 03 '13 at 07:49
  • @JanHudec: Bascially, the point I wanted to make was that it'll be in a section which is read-only. Since data section has both variants (r/w and r/o), it made more sense to write it as code segments, like fayyazkl says. Changed and linked it to the answer now. – legends2k Oct 03 '13 at 07:53
  • A question: if this literal was a #define LITERAL "my string", where would it be placed? Data segment? – Marco A. Oct 03 '13 at 10:40
  • @DavidKernin: It would still be placed in the read-only data segment, since a `#define`d string is just the same from compiler's viewpoint; the preprocessor would've replaced your macro with the string by the time compiler sees the code. – legends2k Oct 03 '13 at 10:55
1

Since you marked this question with the C++ tag (and not the C tag), I'd suggest you to just use std::string as return value:

std::string returnErrorString(int errorCode)
{
   switch(errorCode)
    ...
   return "This error code means that...";
}

(Unless e.g. this is a pure-C interface function exported by some DLL that you want to make usable from different versions of VC++ compilers. In this case you can't have STL classes at the boundaries. But in this case you must clearly state in the documentation that the returned const char * string must not be deleted by the caller code.)

In modern C++, unless there is a strong requirement for high-performance in some tight loop, just use a robust convenient string class like std::string instead of C-like const char*.

Mr.C64
  • 41,637
  • 14
  • 86
  • 162