Does garbage collection happen when we initialize a char array with a string literal in c?

后端 未结 5 1730
生来不讨喜
生来不讨喜 2021-01-25 12:20

When we write the following line of code in C,

      char local_arr[] = \"I am here\";

the literal \"I am here\" gets stored in the read only

相关标签:
5条回答
  • 2021-01-25 12:23

    C does not have garbage collection, so if you forget to deallocate allocated memory with the proper deallocator, you get a memory leak.
    While sometimes a conservative garbage collector like the Boehm collector is used, that causes lots of extra headaches.

    Now, there are four types of memory in C:

    • static memory: This is valid from start to end. It comes in flavors logically read-only (writing is Undefined Behavior) and writeable.
    • thread-local memory: Similar to static memory, but distinct for each thread. This is new-fangled stuff, like all threading support.
    • automatic memory: Everything on the stack. It is automatically freed by leaving the block.
    • dynamic memory: What malloc, calloc, realloc and the like return on request. Do not forget to free resp. using another appropriate deallocator.

    Your example uses automatic memory for local_arr and leaves the implementation free to initialize it to the provided literal whichever way is most efficient.

    char local_arr[] = "I am here";
    

    That can mean, inter alia:

    • Using memcpy/strcpy and putting the literal into static memory.
    • Constructing the array on the stack by pushing the parts, thus putting it into the executed instructions.
    • Anything else deemed opportune.

    Also of interest, C constant literals have no identity, so can share space.
    Anyway, using the as-if rule, many times static (and even dynamic / automatic) variables can be optimized away.

    0 讨论(0)
  • 2021-01-25 12:25

    Not an answer (Deduplicator already has given a good one, I think), but maybe this'll illustrate your problem…

    Consider the following C code:

    #include <stdio.h>
    
    int main() {
        char foo[] = "012";
        /* I just do something with the array to not let the compiler
         * optimize it out entirely */
        for(char *p=foo; *p; ++p) {
            putchar(*p);
        }
        putchar('\n');
        return 0;
    }
    

    with the assembler output (with GCC on my machine):

    [...]
    .LC0:
        .string "012"
    [...]
    main:
    [...]
        movl    .LC0(%rip), %edi
    

    where you have a string in read-only memory (and that string will persist from program startup until exit). When I change the line initializing foo to

        char foo[] = "0123";
    

    GCC thinks it's worth doing it this way:

        movl    $858927408, (%rsp)  # write 858927408 long (4 bytes) to where the stack pointer points to
        movb    $0, 4(%rsp)         # write a 0 byte to the position 4 bytes after where the stack pointer points to
    

    858927408 is 0x33323130 (0x30 is the ASCII code for '0', 0x31 for '1' and so on); in the latter case the string isn't stored at read-only memory, it is stored in the instructions itself. In both cases, the array you eventually access is always on the stack. And you never have the ability to access the string literal in read-only memory in such a case, even if it exists.

    HTH

    0 讨论(0)
  • 2021-01-25 12:35

    Arrays are stored in cml (i.e contiguous memory locations) depending of their scope type. For example global (static) arrays would be saved in the Block Started by Symbol (bbs) which is a part of the data segment, while local are created as a stack in the computer memory. It is a string, because each element from the array points to its next, forming sequence of characters, which forms the string. editing according to the new changes from the question Doing so:

    char str[] = "Hello World";
    

    You do:

    char str[] = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '\0'};
    

    Since the last character is '\0' / NULL / 0 You don't fill information into the last segnificent block of memory, where the data type is stored. In that case, you will terminate the string and you won't receive leaks. Thats just how C handles char arrays and especially strings. They are null-terminated strings. A lot of functions like strlen works only if there is a null terminator.

    Also if you use dynamicly created arrays they will be stored in the heap. As i know the heap is nothing much, basically it provides an environment for allocation and manages the memory for that purpose.

    0 讨论(0)
  • 2021-01-25 12:40

    String Literals are stored in static area. When you copy string literals to a local variable, there will be two copies: static area and stack. The copy in static area will not be deleted. There is no GC in C. But if you use a pointer in a function, you can access the string.

    #include <stdio.h>
    
    char *returnStr()
    {
        char *p="hello world!";
        return p;
    }
    
    char *returnStr2()
    {
        char p[]="hello world!";
        return p;
    }
    int main()
    {
        char *str=NULL;
        char *str2=NULL;
        str=returnStr();
        str2 = returnStr2();
        printf("%s\n", str);
        printf("%s\n", str2);
        getchar();
        return 0;
    }
    

    So in the first function, it will print string because it uses a pointer. In the second function, the string in stack will be deleted so it will print garbage.

    0 讨论(0)
  • 2021-01-25 12:43

    The program doesn't create a new string each time the loop hits it. There's only one string, which already exists, and the literal simply refers to that array.

    What happens is that when the compiler sees a regular string literal, it creates* a static array of char (C11 §6.4.5/6, C99 §6.4.5/5) containing the string's contents, and adds the array (or code to create it) to its output.*

    The only allocation that happens in the function is with char local_arr[] =..., which allocates enough space for a copy of the string's contents. Since it's a local, it is effectively released when control leaves the block that defined it. And due to the way most compilers implement automatic storage (even for arrays), it basically can't leak.

    * (Each literal might end up in its own array. Or, identical string literals might refer to the same array. Or, in some cases, the array might even be eliminated entirely. But that's all implementation-specific and/or optimization-related stuff, and is irrelevant for most well-defined programs.)

    0 讨论(0)
提交回复
热议问题