【问题标题】:memory leak, pointer to literal内存泄漏,指向文字的指针
【发布时间】:2017-12-20 13:02:21
【问题描述】:

我学会了不要让指针指向文字,因为它会导致内存泄漏。但是当我分配一个指向文字的指针时,它仍然指向与以前相同的地址:

    unsigned maxlen = 20;
    char* testpointer = new char[sizeof(char) * maxlen]; //Pointer points to RAM
    cout << "&testpointer = " << &testpointer << endl;

    strncpy(testpointer, "Happy Eastern", 13);
    cout << "&testpointer = " << &testpointer << endl;

    testpointer = "Merry Christmas"; // I know I shouldn't do this
    cout << "&testpointer = " << &testpointer << endl;

我每次仍然得到相同的内存地址:

&testpointer = 0x28fc60
&testpointer = 0x28fc60
&testpointer = 0x28fc60

当我让指针指向文字时,地址不应该改变吗? 我认为我用 new 分配的内存应该在 RAM 中,而文字应该在 ROM 中,它应该有不同的地址。我错了吗?

谢谢你,菲利普

【问题讨论】:

  • 区分指针本身的地址和指针指向的地址。再说了,你学错了。
  • 使用 std::string,而不是 char 数组和 str* 函数。

标签: c++ pointers memory-leaks


【解决方案1】:

您的cout 指令正在打印名为testpointer 的变量的地址。这是当前函数的堆栈帧中的某个位置。与testpointer的值无关,也与testpointer指向的值无关。

另外,要么告诉你不应该让指针指向文字的人是疯了,要么你不明白他们对你说了什么。让指针指向文字绝对没有问题。

【讨论】:

    【解决方案2】:

    &amp;testpointer 是指向变量testpointer 的指针。这是变量本身的存储位置。

    如果您想打印testpointer 指向的位置,则打印其(作为void*,否则operator&lt;&lt; 会将其打印为字符串):

    std::cout << "testpointer = " << static_cast<void*>(testpointer) << '\n';
    

    还要注意,在现代计算机上确实没有 ROM。可执行映像从磁盘加载到虚拟内存(“RAM”)中,其中包括常量字符串文字(实际上是常量字符数组)等数据。

    此外,您可以拥有指向常量字符串文字的指针,但它们实际上应该是指向 const char 的指针,因为常量字符串文字是常量。问题在于变量的重新赋值。你会遇到同样的问题,例如

    unsigned maxlen = 20;
    char* testpointer = new char[sizeof(char) * maxlen];
    // ... stuff happens...
    testpointer = new char[some_other_size];
    

    如果在第二个new[] 之前没有delete[],那么你就有内存泄漏。

    最后是关于您使用std::strncpy 的警告:它不会在末尾添加终止'\0'。这是因为您提供的大小(第三个参数)小于或等于源字符串的长度,在这种情况下,函数不会添加终止符。所以不要试图打印“字符串”的内容或将其用作“字符串”。

    【讨论】:

      【解决方案3】:

      你的问题有两个误解。

      一个,您打印的是testpointer地址,而不是它的,所以它显然没有改变。如果您将&amp;testpointer 替换为static_cast&lt;void*&gt;(testpointer),您将看到不同之处。请注意,强制转换是必要的,因为 &lt;&lt; 被重载,char* 打印字符而不是指针本身。

      两个

      不要让指针指向文字,因为它会导致内存泄漏

      根本不是真的。当且仅当您有一些动态分配的内存并丢失对该内存的任何引用时,才会发生泄漏;换句话说,如果您不再有指向该内存的指针。在这种情况下,您不再有办法释放该内存,因此您泄漏它。

      这通过执行以下操作序列在您的程序中发生:

      char* testpointer = new char[sizeof(char) * maxlen];
      testpointer = "Merry Christmas";
      

      其中任何一个都可以单独使用(1),但它们一起会导致泄漏:

      1. 首先,分配内存
      2. 然后,您忘记了它的地址(通过将指针指向别处)。

      请注意,所涉及的文字是无关紧要的。这将是完全相同的泄漏:

      char* testpointer = new char[sizeof(char) * maxlen];
      testpointer = nullptr;
      

      这样:

      char* testpointer = new char[sizeof(char) * maxlen];
      testpointer = new char[sizeof(char) * maxlen];
      

      (1) 除非您将 char * 指向字符串文字,这是自 C++11 以来不允许的,因为字符串文字是 const。为此,您需要const char *

      【讨论】:

        【解决方案4】:

        我学会了不要让指针指向文字,因为它会导致内存泄漏。

        指向字符串字面量不会导致内存泄漏。可以指向字符串文字。

        顺便说一句,您的程序确实会泄漏内存。


        但是当我分配一个指向文字的指针时

        你的程序在初始化后没有分配指针。

        它仍然指向与以前相同的地址:

        您不会流式传输指针指向的地址。您在指针变量上使用 addressof 运算符,因此您可以流式传输存储指针的地址。即使您确实分配了指针,这也不会改变。


        当我让指针指向文字时,地址不应该改变吗?

        指针变量的地址不会改变。但是它指向的地址(即指针的值)会改变。但是你既没有指向一个字符串文字,也没有观察到指向的地址。

        【讨论】:

          猜你喜欢
          • 2019-04-18
          • 1970-01-01
          • 2013-11-30
          • 1970-01-01
          • 1970-01-01
          • 2017-03-10
          • 2013-04-06
          • 1970-01-01
          • 2012-09-08
          相关资源
          最近更新 更多