开发者

Holding variables in memory, C++

Today something strange came to my mind. When I want to hold some string in C (C++) the old way, without using string header, I just create array and store that string into it. But, I read that any variable definition in C in local scope of function ends up in pushing these values onto the stack.

So, the string is actually 2* bigger than needed. Because first, the push instructions are located in memory, but then when they are executed (pushed onto the stack) another "copy" of the string is created. First the push instructions, than the stack space is used for one string.

So, why is it this way? Why doesn't compiler just add the string (or other variables) to the program instead of creating them once again when executed? Yes, I know you cannot just have some data inside p开发者_开发问答rogram block, but it could just be attached to the end of the program, with some jump instruction before. And than, we would just point to these data? Because they are stored in RAM when the program is executed.

Thanks.


There are a couple of ways of dealing with static strings in C and C++:

char string[] = "Contents of the string";
char const *string2 = "Contents of another string";

If you do these inside a function, the first creates a string on the stack, about like you described. The second just creates a pointer to a statically string that's embedded into the executable, about like you imply that you want.


A very good question indeed. You do know that using static keyword on a variable (definition) EDIT: declaration does just what you described, right?

As far as locals are concerned, performance optimization is the key. A local variable cannot be accessed outside the scope of a function. Why then would the compiler try to persist memory for it outside of the stack?


It is not how it works. Nothing gets "pushed", the compiler simply reserves space in the stack frame. You cannot return such a string from the function, you'll return a pointer to a dead stack frame. Any subsequent function call will destroy the string.

Return strings by letting the caller pass a pointer to a buffer, as well as an argument that says how large the buffer is so you won't overrun the end of the buffer when the string is too long.


If you have:

extern void some_function(char * s, int l);

void do_it(void) {
     char str[] = "I'm doing it!";
     some_function(str, sizeof(str) );
}

This would turn into something like (in psudo asm for a made up processor):

.data
local .do_it.str       ; The contents of str are stored in a static variable
.text   ; text is where code lives within the executable or object file
do_it:
    subtract (sizeof(str)) from stack_pointer        ; This reserves the space for str, sizeof(str)
                                                     ; and a pointer to str on the stack

    copy (sizeof(str)) bytes from .do_it.str to [stack_pointer+0]   ; this loads the local variable
                                               ; using to the memory at the top of the stack
                                               ; This copy can be a function call or inline code.

    push sizeof(str)         ; push second argument first
    push stack_pointer+4     ; assuming that we have 4 byte integers,
                             ; this is the memory just on the other side of where we pushed
                             ; sizeof(str), which is where str[0] ended up

    call some_function

    add (sizeof(str)+8) to stack_pointer          ; reclaim the memory used by str, sizeof(str),
                                                  ; and the pointer to str from the stack
    return

From this you can see that your assumption about how the local variable str is created aren't completely correct, but this still is not necessarily as efficient as it could be.

If you did

void do_it(void) {
     static str[] = "I'm doing it!";

Then the compiler would not reserve the space on the stack for the string and then copy it onto the stack. If some_function were to alter the contents of str then the next (or a concurrent) call to do_it (in the same process) would be using the altered version of str.

If some_function had been declared as:

extern void some_function(const char * s, int l);

Then, since the compiler can see that there are no operations that change str within do_it it could also get away with not making a local copy of str on the stack even if str were not declared static.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜