【问题标题】:Possible memory leak when returning pointer (array) (C++)返回指针(数组)时可能存在内存泄漏(C++)
【发布时间】:2019-07-17 03:39:10
【问题描述】:

考虑一下 C++ 中的代码 sn-p:

int *foo() {
    int *y = new int[1000];
    return y;
}

int main() {
    int *x = new int [1000];
    x = foo();
    delete[] x;
    return 0;
}

x 被创建时,它指向一个内存地址。当foo() 被调用时,一个新的指针y 被创建,指向一个不同的地址,但是x 被设置为y 拥有的地址。因此,当它被删除时,新地址的内存被释放,但x 拥有的原始地址被泄露。对吗?

此外,我在调用foo() 之前调用delete[] x 对sn-p 进行了轻微更改,它仍然编译并运行:

int *foo() {
    int *y = new int[1000];
    return y;
}

int main() {
    int *x = new int [1000];
    delete[] x;
    x = foo();
    delete[] x;
    return 0;
}

这是否意味着我阻止了泄漏?最后一个问题,如果我在声明x时没有初始化它,但又不提前删除它,是不是指向了会被泄露的内存?如下:

int *foo() {
    int *y = new int[1000];
    return y;
}

int main() {
    int *x;
    x = foo();
    delete[] x;
    return 0;
}

作为旁注,我知道使用向量和/或唯一指针更安全,但我对上面代码的功能感到好奇,特别是当指针被声明但稍后初始化时会发生什么。

【问题讨论】:

  • 格式正确的问题;谢谢!

标签: c++ pointers memory-management memory-leaks


【解决方案1】:

创建 x 时,它指向一个内存地址。当 foo() 被调用时,一个新的指针 y 被创建,指向一个不同的地址,但是 x 被设置为 y 的地址。因此,当它被删除时,新地址的内存被释放,但 x 拥有的原始地址被泄露。对吗?

是的。

这是否意味着我阻止了泄漏?

是的。

还有最后一个问题,如果我在声明x的时候没有初始化x,但又不提前删除,是不是指向了会泄露的内存?

没有。

附带说明,我知道使用向量和/或唯一指针更安全

当然。即使没有这些,您的代码也可能很多更清楚地了解内存所有权,因此您的问题甚至不会出现,但切换到标准容器/智能指针确实可以从源头解决问题,我强烈推荐这个。


tl;dr:到目前为止,你说的都是对的

【讨论】:

  • 所以按照我的理解,一个未初始化的指针还没有真正指向任何东西。
  • @Daniel Pointers 会指出。一个未初始化的指针指向某个地方,但它并不指向任何可以安全使用的东西。在现代系统中,它通常指向即时死亡,而严峻的垃圾收集器非常乐意收割。但有时它最终会指向已分配给程序的内存,这些可以是绝对的 来查找和调试。 这里的代码与那里的代码无关,只是覆盖了那里的内存,当程序搞砸了那边你可能不会从调试代码开始这边
  • @Daniel 正确。
  • @user4581301 “指针会指向。一个未初始化的指针指向某个地方,但它没有指向任何可以安全使用的东西” 这是语义问题。很容易争辩说,未初始化的指针确实 not “指向某处”,因为没有 UB 就无法观察到它的值(它的值未指定)。在实践中,它有一些任意数值,您可以将其描述为“指向可能不安全的地方”,但这并不是语言真正看待它的方式,也不是您应该看待它的方式。
【解决方案2】:

在你上面的 sn-p 中:

int *x = new int [1000];
x = foo();
delete[] x;

您分配了一个指向 x 的数组指针,但随后通过将 foo() 分配给它来“压扁”它。如果您使用垃圾回收语言(或使用智能指针)工作,那么在这种情况下内存将被回收。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 2013-10-31
    • 2015-12-15
    • 1970-01-01
    相关资源
    最近更新 更多