zoukankan      html  css  js  c++  java
  • C++ delete 两次

    转载自:http://blog.csdn.net/jxluofeng/article/details/19766801

    《问题》危险的代码:

       int* p=new int(1);
       delete p;
       delete p;

    探讨一:

       连续两次对同一个指针delete ,会造成严重的错误。编译器会检测出这样的错误吗?或许一些编译器会的,但别太过指望编译器。

    探讨二:

       第一次delete后,p自动为空(NULL)了吗?不是的。

    探讨三:

       在delete之前会自动检查p是否为空(NULL),如果为空(NULL)就不再delete了吗?确实是如此。

    探讨四:

       删除为空(NULL)的指针是不会有任何问题的吗?确实是如此。

    探讨五:

       #define SAFE_DELETE(p) delete (p); p = 0;

       这样就就万事大吉了吗?好像不是的。

       delete p+1;//在C++中是正确的

       SAFE_DELETE(p+1)将会导致错误

    探讨六:

       没有好的方法解决重复释放这样的问题,只能靠程序员的细心了。

    《结论》安全的代码:

       int* p=new int(1);
       delete p;
       p = NULL;

    (1)delete 一次以后,p成了野指针,它作为地址的值还是有效地没还可以访问它以前指向的内存,不过那片内存被重新格式化了;
    (2)p不等于NULL,用 if(p) 语句不能判断它指向的内存是否有效(此时它指向的内存无效,p本身有效);
    (3)delete 一次以后,不能再次delete,否则会报错;
    (4)此时如果误用p指针,仍然可以修改内存的值和从该处取出数值,但此时数据不受保护,该内存空间可能被重新被分配给别的变量;
    (5)如果p指向的空间再次被new函数分配,即使是分配给别的指针,即使分配大小与原来不一样,p又恢复了效力,可以改变内存的值,甚至可以重新被delete,p的作用与新分配的指针一样;

    转载自: C++ 一不小心被delete两次

    2012-09-11 12:10 by 捣乱小子, 2720 阅读, 31 评论, 收藏编辑

    2012-09-11 18:04:看到园里朋友们这么热心,有那么一会心里好兴奋。:)

    2012-09-11 下午:本文曾出现很严重的错误,但不要紧,感谢园友们的即使指正。

    不喜欢程序语言的

    C++类中,有时候使用到传值调用(对象实体做参数),遇到这种情况,可要小心了!特别是当你所传值的对象生命周期较长,而非临时对象(生命周期段)的时候。来看看下面的情况:

    #include <iostream>
    using namespace std;
     
    class Text
    {
    private:
        char * str;
     
    public:
        Text(){str = new char[20];::memset(str,0,20);}
        void SetText(char * str)
        {
            strcpy(this->str,str);
        }
        char * GetText() const{return str;}
        ~Text()
        {
            cout << "~Text Destruction" << endl;
            delete [] str;
            cout << "~Text Over" << endl;
        }
    };
     
    void Print(Text str)
    {
        cout << str.GetText() << endl;
    }
     
    int main()
    {
        Text t;
        t.SetText("abc");
        Print(t);
        return 1;
    }

    上面执行的结果程序崩溃了。原因:

    Print(Text str)在对str进行复制构造的时候,没有进行深度拷贝;当 Print退出的时候,因为是临时对象(函数初始时构造),对str进行析构,此时还没有任何破绽;但回到main,继而退出main 的时候,又对t进行析构,但此时t内的str中的内容已经被销毁。由于对一内存空间实施了两次销毁,于是出现内存出错。

    解决方法:

    1. 重写浅拷贝。像一下版本,不同的情况要作出适当的调整: 
      #include <iostream>
      using namespace std;
       
      class Text
      {
      private:
          char * str;
       
      public:
          Text(){str = new char[20];::memset(str,0,20);}
          Text(Text &t)
          {
              str = new char[20];
              strcpy(str,t.GetText());
          }
          void SetText(char * str)
          {
              strcpy(this->str,str);
          }
          char * GetText() const{return str;}
          ~Text()
          {
              cout << "~Text Destruction" << endl;
              delete [] str;
              cout << "~Text Over" << endl;
          }
      };
       
      void Print(Text str)
      {
          cout << str.GetText() << endl;
      }
       
      int main()
      {
          Text t;
          t.SetText("abc");
          Print(t);
          return 1;
      }
    2. (推荐)不使用传值调用。就像下面书写如下Print版本: 
      void Print(Text &str)
      {
          cout << str.GetText() << endl;
      }
    3. 评论中的小伙伴还提供了一个方法,很值得推荐,同时这也是编程良好的习惯:指针在使用的时候需要作空判断,在删除指针时候需要置空。

    后记——语言的探讨

    C++,以至于其他的程序语言,都是伟大的创造。他们是规则的世界,一愣一脚皆规则。当对某一规则有所熟知之后,就似发现新大陆似的。但想想,这些规则可经不起碰撞打击,殃及的是coder,是我们。这些规则不像1+1=2,“三点定面”来的铁定,总之比起数学理论来说,似乎程序规则脆弱很多,总之在它们身上看到的价值是有限的,总我还是选择了计算机...为之奈何,不得而知。

  • 相关阅读:
    库头文件的导入导出宏
    VC 注册表读写
    改变QTableWidget 行高
    QMenu,QT的菜单添加
    error LNK2023: bad DLL or entry point 'msobj80.dll' 解决方法
    QT,QAction中的ToolTip
    QT 修改QTableWidget表头
    VS2008中 没有QT的代码智能提示
    VC 创建托盘,托盘tooltip。右键托盘菜单,点击别的地方会隐藏掉的问题。
    GDI+ 双缓冲
  • 原文地址:https://www.cnblogs.com/sanghai/p/6828695.html
Copyright © 2011-2022 走看看