-1

I have a question about C-style string symbolic constants and dynamically allocating arrays.

const char** name = new const char* { "Alan" };
delete name;

when I try to delete name after new'ing a piece of memory, the compiler suggest to me to use delete instead of delete[]. I understand name only stores the address of the pointer to the only-read string.

However, if I only delete the pointer to pointer (which is name), will the string itself cause a memory leak?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Alan LAI
  • 3
  • 2
  • 5
    You should `delete` only what you `new`ed and nothing else. No, C-strings should not be `delete`d. – Evg Mar 16 '21 at 16:50
  • https://stackoverflow.com/questions/2425728/delete-vs-delete-operators-in-c – πάντα ῥεῖ Mar 16 '21 at 16:50
  • 2
    You `delete` what you have `new`ed. In this case, you delete `name`. Keep in mind, that the whole exercise is rather moot. `const char* name = "Alan"` should serve you well and requires no deletions or `new`itions. – SergeyA Mar 16 '21 at 16:50
  • @SergeyA If I'm reading Pavta's link properly would `delete [] name` be appropriate? – Ruzihm Mar 16 '21 at 16:52
  • 1
    @Ruzihm did you use `new []`? – user253751 Mar 16 '21 at 16:53
  • @Ruzihm, no, because you did not do `new[]`. Those things always come in pairs. – SergeyA Mar 16 '21 at 16:56
  • It may help to visualize the example as `T* name = new T { "Alan" ); delete name;` where `T` just happens to be `const char *`. – François Andrieux Mar 16 '21 at 17:02
  • Ah, I see, you would use `delete [] name;` if you had used `const char ** name = new const char*[1]{"Alan"};` because of the difference between an array of a single element and a pointer. Is that right? – Ruzihm Mar 16 '21 at 17:21
  • @Ruzihm, I am actually confusing about `const char*`, I think it is similar to `char[]` which also stores string. Similarly, if I want to delete `const char*`, I should use `detele[]`. Otherwise, I will only delete the pointer to the string, not the string itself. – Alan LAI Mar 16 '21 at 17:34

1 Answers1

1

As the comments above indicate, you don't need to manage the memory that "Alan" exists in. Let's see what that looks like in practice.

I made a modified version of your code:

#include <iostream>

void test() {
    const char** name;
    name = new const char* { "Alan\n" };   
    delete name;
}

int main()
{
    test();
}

and then I popped it into godbolt and it shows what's happening under the hood. (excerpts copied below)

In both clang and gcc, the memory that stores "Alan\n" is in static memory so it always exists. This is how it creates no memory leak even though you never touch it again after mentioning it. The value of the pointer to "Alan\n" is just the position in the program's memory, offset .L.str or OFFSET FLAT:.LC0.

clang:

test():                               # @test()
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     edi, 8
        call    operator new(unsigned long)
        mov     rcx, rax
        movabs  rdx, offset .L.str
        mov     qword ptr [rax], rdx
        mov     qword ptr [rbp - 8], rcx
        mov     rax, qword ptr [rbp - 8]
        cmp     rax, 0
        mov     qword ptr [rbp - 16], rax       # 8-byte Spill
        je      .LBB1_2
        mov     rax, qword ptr [rbp - 16]       # 8-byte Reload
        mov     rdi, rax
        call    operator delete(void*)
.L.str:
        .asciz  "Alan\n"

gcc:

.LC0:
        .string "Alan\n"
test():
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     edi, 8
        call    operator new(unsigned long)
        mov     QWORD PTR [rax], OFFSET FLAT:.LC0
        mov     QWORD PTR [rbp-8], rax
        mov     rax, QWORD PTR [rbp-8]
        test    rax, rax
        je      .L3
        mov     esi, 8
        mov     rdi, rax
        call    operator delete(void*, unsigned long)
Ruzihm
  • 19,749
  • 5
  • 36
  • 48
  • I guess I need more knowledge in the future to understand the assembly code, but anyway, thank you. – Alan LAI Mar 16 '21 at 18:30