3

Let's say I have a function with the following specification:

void example(char* str)

If I pass in a string argument, such as:

example("testing");

Is the value of "testing" dynamically allocated on the heap, so I'll be able to use it after the scope that made the function call to "example" is destroyed (and need to free it later), or is it a local variable on the stack, so I'll need to make a new string using malloc and store the value in there if I want it to persist in, say, a hashmap?

Thanks.

Paul B
  • 349
  • 4
  • 14
  • possible duplicate of [Is a string literal in c++ created in static memory?](http://stackoverflow.com/questions/349025/is-a-string-literal-in-c-created-in-static-memory) – paddy Jul 02 '13 at 03:34
  • @paddy - Despite similar names, C and C++ are different beasts. But you are correct in that there are certainly duplicates of this one. – mouviciel Jul 02 '13 at 05:39
  • 1
    Well, I remembered answering this in the past, but was unable to list [my answer](http://stackoverflow.com/questions/14468697/where-is-memory-allocated-with-a-const-char-pointer/14468729#14468729) as a duplicate because the question was subsequently closed and flagged as a duplicate. So instead, I listed *that* duplicate, which happened to be phrased in terms of C++. – paddy Jul 02 '13 at 05:42

3 Answers3

8

When you write "testing" in your program, it will be compiled as a string literal, and room for it will be allocated during compile time. When you get a pointer to it, it's a pointer to that place in memory. You don't need to allocate it with malloc(), and you also should not free() it. But it's also not a good idea to try to modify its content, because the compiler will likely put it in a readonly area (that is, it's compiled as a constant) -- the following program, for example, crashes on my Linux desktop:

#include <stdio.h>
int main() {
    char *a = "abc\n";
    a[0]='X';
    printf(a);
    return(0);
}
Jay
  • 9,585
  • 6
  • 49
  • 72
3

In C, a string between quotes, "such as this", is called a string literal.

String literals, such as what you gave above, are not dynamically allocated. Typically, they're allocated at compile and/or link time, and may be allocated in read-only memory. (That is why, in C++, string literals are const char as opposed to char.)

Under the hood, some compilers stash "testing" in a string table, generating a special pointer to it. It's roughly equivalent to this:

char *const compiler_generated_pointer_to_testing = (char *) (compiler_generated_string_table + 12345);

...

const char compiler_generated_string_table[] = { 
    ...
    't', 'e', 's', 't', 'i', 'n', 'g', 0, 
    ...
};

...

example( compiler_generated_pointer_to_testing );

That's one way it could play out. Many other implementations are legal. In any case, the implementation details are probably besides the point. The real main points to remember are:

  • Compile-time string literals should be treated as const, even if the compiler doesn't require you to declare pointers to them as const char *.
  • They are allocated at compile and/or link time, not on the heap or the stack.
  • Two instances of the same string (ie. foo("testing") and bar("testing") in different parts of the program) are not guaranteed to be distinct pointers, nor are they guaranteed to be the same pointer value.
  • You must never free() a string literal.
  • You must never write to a string literal.
  • A string literal will remain available through the life of a program, so it works fine as, say, a hash key.

Got all that? Any questions?

Joe Z
  • 17,413
  • 3
  • 28
  • 39
  • 2
    FWIW, the only real reason string literals aren't `const char` in C is that C didn't initially define them that way. By the time "const correctness" gained steam as a programming paradigm, the C language had significant installed base that would break if string literals retroactively became `const`. C++ didn't have that burden. If you really want to be belt-and-braces with your code, declare your pointers `const` whenever possible. No less a luminary than John Carmack has become a `const` nazi, in his own words: http://www.phoronix.com/scan.php?page=news_item&px=MTI3NDQ – Joe Z Jul 02 '13 at 03:47
1

Most commonly it will be stored as a string literal in the read only part of the executable. You can actually manually verify that by compiling your program with the -S flag.

It will produce an assembly executable called name_of_your_app.s in which you can find the string literal (it will be located in the so called data segment).

Occasionally the compiler can put in the code segment or depending on the optimisation level it will simply optimise it away (most easily checked by creating a string literal that is not used anywhere and then compiling with the -O3 flag on GCC).

Here's a (contrived) example:

int main() 
{
    char *a = "Hai!";

    return 0; 
}

If I compiled it with no special flags the string literal is still there:

$ gcc -S main.c
main.c: In function ‘main’:
main.c:9:11: warning: unused variable ‘a’ [-Wunused-variable]
$ cat main.s | grep Hai
    .string "Hai!"

However, once I crank up the optimisation level, it's no longer the case:

$ gcc -S -O3 main.c
main.c: In function ‘main’:
main.c:9:11: warning: unused variable ‘a’ [-Wunused-variable]
$ cat main.s | grep Hai
$

It looks like this answer addresses the same issue.

Community
  • 1
  • 1
Nobilis
  • 7,310
  • 1
  • 33
  • 67
  • There's no guarantee that it will be stored read-only, though that's a common implementation. – Keith Thompson Jul 02 '13 at 04:26
  • Thanks for your comment, I guess occasionally it can be found in the code segment or is optimised away by the compiler. I'll add an update to my answer. – Nobilis Jul 02 '13 at 05:28
  • Or it can be stored in read/write memory. Attempting to modify a string literal has undefined behavior, so it *can* "work", depending on the implementation. – Keith Thompson Jul 02 '13 at 15:59