【问题标题】:Isn't it ok in terms of memory leakage etc在内存泄漏等方面可以吗
【发布时间】:2011-12-29 09:21:10
【问题描述】:

我开始学习 c++ 已经有两个月了,我不太确定我的项目做错了什么。我有一个具有初始大小的动态分配数组,并且在我想更改它的大小之后。我想知道为什么下面的代码是错误的

    int *firstPtr = new int [4];
    for (int i = 0; i < 4; i++) {
        firstPtr[i] = i;
    }

    int *tempPtr = new int[5];
    for (int i = 0; i < 4; i++) {
        tempPtr[i] = firstPtr[i];
    }
    tempPtr[4] = 4;
   // firstPtr = new int[5];
    firstPtr = tempPtr;
    delete tempPtr;

     for (int i = 0; i < 5; i++) {
        cout << firstPtr[i] << endl;
    }

因为输出是:

10757752
10753936
2
3
4


PS:我不能为此使用 realloc/malloc 等,因为该项目只是关于指针。没有他们我怎么能纠正这个问题。

【问题讨论】:

    标签: c++ pointers memory-leaks dynamic-memory-allocation


    【解决方案1】:
    firstPtr = tempPtr;
    

    第一个 Ptr 现在指向与 tempPtr 相同的内存。

    delete tempPtr;
    

    您现在正在删除该内存,firstPtr 和 tempPtr 都指向同一个内存。

    for (int i = 0; i < 5; i++) {
        cout << firstPtr[i] << endl;
    }
    

    您正在访问已删除的内存,打印的值可以是任何值。

    要得到我假设你想要的,你需要删除该行

    firstPtr = tempPtr;
    

    或者删除for后面的内存:

    for (int i = 0; i < 5; i++) {
        cout << firstPtr[i] << endl;
    }
    delete[] tempPtr;
    

    请注意,在第二种情况下,您将遇到内存泄漏,因为firstPtr 最初指向的内存不再可访问。

    完整且正确的代码如下:

    int *firstPtr = new int [4];
    for (int i = 0; i < 4; i++) {
        firstPtr[i] = i;
    }
    
    int *tempPtr = new int[5];
    for (int i = 0; i < 4; i++) {
        tempPtr[i] = firstPtr[i];
    }
    tempPtr[4] = 4;
    
    for (int i = 0; i < 5; i++) {
        cout << firstPtr[i] << endl;
    }
    delete[] tempPtr;
    delete[] firstPtr;
    

    一些 ASCII 艺术:

    firstPtr = new int[4];
    
    firstPtr
       |
    +------++------++------++------+
    |      ||      ||      ||      |
    |      ||      ||      ||      |
    +------++------++------++------+
    
    for (int i = 0; i < 4; i++) {
        firstPtr[i] = i;
    }
    
    firstPtr
       |
    +------++------++------++------+
    |   0  ||   1  ||   2  ||   3  |
    |      ||      ||      ||      |
    +------++------++------++------+
    
    int *tempPtr = new int[5];
        for (int i = 0; i < 4; i++) {
            tempPtr[i] = firstPtr[i];
        }
        tempPtr[4] = 4;
    
    tempPtr
       |
    +------++------++------++------++------+
    |   0  ||   1  ||   2  ||   3  ||   4  |
    |      ||      ||      ||      ||      |
    +------++------++------++------++------+
    

    所以现在,在记忆中,你有:

    firstPtr
       |
    +------++------++------++------+
    |   0  ||   1  ||   2  ||   3  |
    |      ||      ||      ||      |
    +------++------++------++------+
    
    tempPtr
       |
    +------++------++------++------++------+
    |   0  ||   1  ||   2  ||   3  ||   4  |
    |      ||      ||      ||      ||      |
    +------++------++------++------++------+
    

    你的下一行:

    firstPtr = tempPtr;
    

    这样做:

    no longer pointed to by firstPtr
       |
    +------++------++------++------+
    |   0  ||   1  ||   2  ||   3  |
    |      ||      ||      ||      |
    +------++------++------++------+
    
    tempPtr
    firstPtr  -  firstPtr now points here
       |
    +------++------++------++------++------+
    |   0  ||   1  ||   2  ||   3  ||   4  |
    |      ||      ||      ||      ||      |
    +------++------++------++------++------+
    
    delete tempPtr;
    
    tempPtr
    firstPtr  -  firstPtr now points here
       |
    +------++------++------++------++------+
    |   x  ||   x  ||   x  ||   x  ||   x  |
    |      ||      ||      ||      ||      |
    +------++------++------++------++------+
    

    所以现在,tempPtr 指向删除内存。希望这可以解决问题。

    【讨论】:

    • 增加 firstPtr 的大小后,我不需要 tempPtr,因为我的工作已经完成了。为什么我不能只删除指针 tempPtr?
    • @CihadTurhan,你可以,只是不要让 firstPtr 指向同一个位置。
    • 据我了解,我应该保留两个指针,因为当我删除其中一个时,内存被释放,这意味着两个指针都指向不相关的地址。这是真的吗?
    • @CihadTurhan 我编辑了我的答案,希望它能让事情更清楚。指针只是一个包含内存地址的变量。有了firstPtr = tempPtr,两者都指向同一个地址,然后您将其删除,因此两者都将指向已删除的内存。
    • @Cihad: 不,你只需要保留两个指针,以防你做firstPtr = tempPtr;,因为它们指向同一个内存区域。
    【解决方案2】:
    1. 分配给firstPtr 将无法释放被覆盖指针后面的内存
    2. 删除tempPtr会使firstPtr指向的数据失效(输出错误的直接原因)

    解决方案:

    1. 在赋值行“firstPtr = tempPtr;”之前添加删除firstPtr的行
    2. 在“cout tempPtr 的行

    【讨论】:

      【解决方案3】:

      代替

       firstPtr = tempPtr;
       delete tempPtr;
      

      你需要

       delete [] firstPtr;
       firstPtr = tempPtr;
      

      然后,完成后,别忘了

       delete [] firstPtr;
      

      在您的原始帖子中,您首先将 firstPtr 点指向新分配的内存,然后释放它。所以 firstPtr 和 tmpPrt 都指向释放的内存。使用释放的内存是未定义的行为。另外,请考虑使用std::vector&lt;int&gt;s。这将使您的生活更轻松。

      【讨论】:

      • 应该是delete[],而不是delete
      【解决方案4】:

      来了

      firstPtr = tempPtr;
      delete tempPtr;
      

      你看,你把tempPtr的值赋值给firstPtr,这意味着它们指的是同一个内存位置(此时你没有指向旧内存的指针,它曾经被指向由firstPtr),然后你释放(deletetempPtr指向的内存,这实际上是相同的内存。

      正确的方法应该是

      delete firstPtr;
      firstPtr = tempPtr;
      

      【讨论】:

        【解决方案5】:
        firstPtr = tempPtr;
        delete tempPtr;
        

        然后您使用firstPtr,但它与tempPtr 相同,这是您删除的指针。

        试着在纸上画出你堆里发生的事情来理解。

        【讨论】:

          【解决方案6】:

          您正在访问已删除的内存。这是未定义的行为。

          这类似于在调用free() 之后从malloc()ed 指针中读取值。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-07-07
            • 1970-01-01
            • 2011-08-12
            • 1970-01-01
            • 1970-01-01
            • 2014-07-10
            相关资源
            最近更新 更多