【问题标题】:Memory Leaks, Overloading the Assignment Operator, New, Delete, and C++内存泄漏、赋值运算符重载、新建、删除和 C++
【发布时间】:2013-10-20 03:02:10
【问题描述】:

在 C++ 中动态分配内存当然可以使用newdelete 来完成。如果在 C++ 程序过程中不再需要使用new 动态分配的指针,则可以使用delete 来动态释放计算机内存。我认为,如果我没有记错的话,Stroustrep 在他的一本关于 C++ 的书中提到 C 中的 mallocalloc 为编译器而不是程序员提供了“释放”或“创建”内存的选项对比面向对象的“新建”和“删除”。如果我不删除指针,那么我会遇到相当隐蔽的内存泄漏,这不好。

然而,仅仅删除指针——正如 Carrano、Helman 和 Veroff (CHV) 在 Walls and Mirrors 第 2 版中第 151-153 页上的注释——并不能消除指针。相反,delete 会清空指针的内容,但会将指针留在计算机内存空间中的某个位置。

无论如何,CHV 会说在使用 delete 之后必须将指针设置为 NULL 才能摆脱这个“已删除”构造。

在这种情况下,赋值运算符是否被重载以接受 NULL 作为布尔值?换句话说,编译器是否告诉计算机指针应该存在于内存空间中是错误的,这意味着我告诉编译器物理上阻止一堆占据两位空间的电子通过我的计算机运行?我在这里遗漏了什么吗?

【问题讨论】:

  • 这么多……混乱……
  • 这就像那些巨魔科学论文之一。
  • 我的印象是“NULL == 0”将被视为 TRUE,这意味着 NULL 与 FALSE 同义,这意味着指针一旦终止就会变成“布尔”类型的构造这样。我的想法是0“关闭”电子门,而“1”表示门打开。我弄错了吗?

标签: c++ pointers memory memory-leaks


【解决方案1】:

仅仅删除一个指针并不能摆脱指针

确实没有;它销毁指针指向的对象,并释放对象的内存。指针不受影响,最终指向无效内存。

无论如何,CHV 会说在使用 delete 之后必须将指针设置为 NULL 才能摆脱这个“已删除”结构

不,之后指针仍然存在;但是将其设置为 null 将确保它没有指向无效内存,这可以说是更安全的。当然,使用智能指针管理动态对象是一个更好的主意,因此您一开始就永远不会得到一个无效的指针。

在这种情况下,赋值运算符是否被重载以接受 NULL 作为布尔值?

不,NULL 不是布尔值,它是一个空指针常量;一个不指向任何东西的特殊指针值。

换句话说,编译器是否告诉计算机指针应该存在于内存空间中是错误的,这意味着我告诉编译器物理上阻止一堆占据两位空间的电子运行通过我的电脑?

呃,什么?不,它只是告诉指针不要指向任何东西。它当然不会阻止任何电子占据任何空间。

我错过了什么吗?

我认为您缺少的主要思想是指针和它指向的东西是独立的对象,具有不同的生命周期。 delete 将销毁具有动态生命周期的对象,但不会销毁用于引用它的指针。

【讨论】:

    【解决方案2】:

    了解一些历史可能会有所帮助。首先,有 C,带有 malloc 等。例如:

    char *ptr = malloc(100);
    strcpy(ptr, "hello, world!");
    free(ptr);
    printf("%s\n", ptr);   /* BAD - but will PROBABLY print "hello, world!" */
    

    malloc 分配 100 个字节,strcpy 填充它,free() 释放它。 “解除分配”所涉及的只是意味着该内存现在可以被另一个 malloc 调用重用。

    free() 不会重置任何指针,也不会清除内存 - 因此上面的 printf 可能仍会打印字符串,因为(可能)没有任何变化。当然,任何写这种东西的程序员都应该被解雇。

    为了避免错误的使用,因为 free() 不会重置指针,所以我们最好在释放一些内存后立即重置它们:

    free(ptr);
    ptr = NULL;
    printf("%s\n", ptr);   /* Now we get a NULL pointer exception - which is what we want */
    

    我们想要空指针异常,因为在 free() 之后我们不应该使用 ptr 的值。

    对于 C++,所有这些参数都是相同的。 delete 比 free 做了更多的事情——主要是它调用对象的析构函数等,但基本是一样的。指针没有重置,内存仍然存在 - 你确实想知道你是否正在访问未分配给你的内存 - 最好的方法是在删除对象时将指针设置为 null。

    【讨论】:

      【解决方案3】:

      带有nullptrNULL 的空指针用于防止双重删除时崩溃,而不是释放指针实际占用的内存(指针,而不是它指向的内存)。实际指针停止存在的唯一时间是作用域的结束。

      【讨论】:

        【解决方案4】:

        指针本身的生命周期与所有其他变量一样,受范围控制。

        void someFunc()
        {
            int* ptr;
        
        }//ptr dies after this bracket
        

        所以请务必记住在指针超出范围之前释放它所指向的内存,否则您将永远无法再次访问它!

        【讨论】:

          猜你喜欢
          • 2014-10-16
          • 1970-01-01
          • 1970-01-01
          • 2013-04-20
          • 2015-11-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-05-08
          相关资源
          最近更新 更多