【问题标题】:Is there a need to destroy char * = "string" or char * = new char[6]?是否需要销毁 char * = "string" 或 char * = new char[6]?
【发布时间】:2010-09-08 06:32:07
【问题描述】:

我假设char* = "string"char* = new char[6] 相同。我相信这些字符串是在堆而不是堆栈上创建的。那么当我用完它们时我需要销毁它们或释放它们的内存还是它们会被自己销毁?

【问题讨论】:

    标签: c++ memory


    【解决方案1】:

    让我们看看 GCC 4.8 x86-64 Linux 做了什么

    程序:

    #include <cstdio>
    int main() {
        const char *s = "abc";
        char *sn = new char[4];
        sn[3] = '\0';
        std::printf("%s\n", s);
        std::printf("%s\n", sn);
    }
    

    编译和反编译:

    g++ -c -ggdb -o a.o -std=c++98 a.cpp
    objdump -CSr a.o
    

    输出包含:

      const char *s = "abc";
     8:   48 c7 45 f0 00 00 00    movq   $0x0,-0x10(%rbp)
     f:   00 
                         c: R_X86_64_32S .rodata
      char *sn = new char[4];
    10:   bf 04 00 00 00          mov    $0x4,%edi
    15:   e8 00 00 00 00          callq  1a <main+0x1a>
                            16: R_X86_64_PC32       operator new[](unsigned long)-0x4
    1a:   48 89 45 f8             mov    %rax,-0x8(%rbp)
    

    解读:

    • char *s = "abc" 进入 .rodata。所以你不能以任何方式free它。
    • char *sn = new char[4]; 来自 operator new[] 的输出。因此,您应该尽可能释放它。

    【讨论】:

    • 我认为你应该在g++ -ggdb -std=c++98 a.cpp 中添加-c 标志。
    【解决方案2】:

    游戏的名称是“只摧毁你创造的东西”。这是对:

    1. malloc/free
    2. calloc/free
    3. new/delete
    4. new []/delete []

    由于您使用new [] 创建了第二个字符串,因此您有责任使用delete [] 销毁它。完成后致电delete [] string2

    现在,如果您的代码足够复杂并且难以跟踪删除,请考虑使用作用域指针或自动指针。 boost 库中的 boost::scoped_ptr 类是一个很好的起点。还请查看RAII 成语,非常方便且有用的东西。

    【讨论】:

      【解决方案3】:

      它们不一样。您的第一个示例是一个常量字符串,因此绝对不是从堆中分配的。您的第二个示例是 6 个字符的运行时内存分配,它来自堆。你不想删除你的第一个例子,但你需要delete []你的第二个例子。

      【讨论】:

      • "new" 从堆中分配内存,而不是从栈中。 (当然,除非你重写了 new 操作符。)
      • 我的错。我知道。真的。 :-)
      【解决方案4】:

      我假设当我执行char* = "string" 时,它与char* = new char[6] 相同。

      没有。第一个所做的是创建一个常量。修改它是未定义的行为。但要回答你的问题;不,你不必摧毁它们。请注意,尽可能使用std::string

      【讨论】:

        【解决方案5】:

        没有。当您使用malloc 函数(在C 中)或new 运算符(在C++ 中)自己手动分配内存时,您只需要手动释放字符串。如果不使用mallocnew,则char* 或字符串将在堆栈上创建或作为编译时常量。

        【讨论】:

        • 我认为字符串文字分配在.rodata部分而不是堆栈中。
        【解决方案6】:

        没有。当你说:

        const char* c = "Hello World!";
        

        您将 c 分配给一个“预先存在的”字符串常量,它与以下内容不同:

        char* c = new char[6];
        

        只有在后一种情况下,您才在堆上分配内存。所以你会在完成后调用 delete。

        【讨论】:

          【解决方案7】:

          new 始终是一个分配,而定义一个字符串内联实际上将数据嵌入程序本身并且不能更改(一些编译器通过一个聪明的技巧允许这样做,不要打扰)。

          某些编译器会键入内联字符串,因此您无法修改缓冲区。

          char* const sz1 = "string"; // embedded string, immutable buffer
          char* sz2 = new char[10]; // allocated string, should be deleted
          

          【讨论】:

            【解决方案8】:

            您不知道字符串文字的存储位置。它甚至可能是只读内存,所以你的代码应该是这样的:

            const char* c = "string";
            

            new char 数组应该像任何其他动态分配的内存区域一样被删除

            【讨论】:

              猜你喜欢
              • 2014-07-14
              • 2019-07-24
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-01-11
              • 1970-01-01
              • 2013-05-14
              相关资源
              最近更新 更多