6

I'm trying to understand why the following string passing works for my error string. I have made this example from a much bigger source I have.

Why don't I have to specifically allocate memory for the char array which contains my error message? I would have thought that I need to malloc some memory for the string and use the err pointer to indicate the start of this memory.

Is this to do with that fact that its a const char * or is is because I'm printing to standard error?

const char * my_function(int a)
{
    if (a != 1)
        return "a doesn't equal 1!"
    else
        return NULL;
}

int main(int a)
{
    const char *err;
    err = my_function(a);
    if (err)
        fprintf(stderr, "Message = %s\n", err);
        return 1;
    return 0;
}
1

6 Answers 6

12

All string literals are allocated at compile time. They already reside in a read-only section of the program memory when your program is started; they aren't allocated in runtime. You can regard them as constant character arrays. And like any const variable, they remain valid throughout the whole execution of the program.

Sign up to request clarification or add additional context in comments.

4 Comments

"All string literals are allocated at compile time." - For me, this was the most helpful part of all the answers given.
"All string literals are allocated at compile time." Is this wording really correct? I believe nothing is allocated at compile time. If it's allocated at compile time when is it deallocated then?
@Kolyunya Link time then, if you are picky. String literals are typically placed in a section of memory called .rodata.
That is because the string in your sub routine is stored in the shared segment (read only), and it can be returned after the routine exits. If you define it as char str[]="your string", you will not be able to return the value because it's "allocated" on stack. The stack pointer will resume at the end of sub routine. So @Ludin's answer is only partial here.
3

String literals are allocated as const char arrays with static storage duration, so they live for the entire lifetime of the program. The scope they happen to be in is irrelevant -- they always have static storage duration.

That means you can take their address (which happen implicitly if you return a string literal or store it in a const char * variable anywhere) without having to worry about the lifetime of the resulting pointer. The storage for the string literal will never be used for something else.

Comments

3

Please note that your main() will always return 1.

int main(int a)
{
    const char *err;
    err = my_function(a);
    if (err)
         fprintf(stderr, "Message = %s\n",err);
         return 1;
    return 0;
}

The return 1 is indented as if it's under the if (err), but it is not. What you really have is:

int main(int a)
{
    const char *err;
    err = my_function(a);
    if (err)
         fprintf(stderr, "Message = %s\n",err);
    return 1;
    return 0; # Never gets executed.
}

What you want is:

int main(int a)
{
    const char *err;
    err = my_function(a);
    if (err) {
         fprintf(stderr, "Message = %s\n",err);
         return 1;
    }
    return 0;
}

It's for this reason that I always use braces around my blocks, even when they are not strictly necessary.

1 Comment

2

You're returning a string literal. It's being held in static memory, but has an address like any other string. So you can refer to that address at any time. A problem would be if you tried to change the string literal, which I believe is undefined behaviour.

Comments

1

It is because the string is stored in the data section of your program. When you type "a doesn't equal 1!", memory is allocated and that value is written into it.

You function merely returns the pointer to that slice of memory and fprintf is happy to read from it.

6 Comments

So how much memory is allocated? Just enough for my returned string?
What if I had another function which returned a const char * to the same address? but was longer?
Just enough for your string, check out the resulting assembly to find out how it works.
I don't understand your second question, what do you mean with "but was longer" ? Another function returning the same pointer, would work without issue. You can use %p in printf functions to see the actual address of where the pointer points to.
@Markus String literals are "allocated" when the program compiles (when run, the OS will copy code and data into memory, basically allocating actual memory for them). They are stored inside the binary. You can use a tool like strings on Unix to view them.
|
0

Don't be too optimistic. That is because the string in your sub routine is stored in the shared segment (read only), and it can be returned after the routine exits. If you define it as char str[]="your string", you will not be able to return the value because it's "allocated" on stack. The stack pointer will resume at the end of sub routine.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.