• 关于new,delete,malloc,free的一些总结


    • 首先,new,delete都是c++的关键字并不是函数,通过特定的语法组成表达式,new可以在编译的时候确定其返回值.可以直接使用string *p=new string("asdfgh");来直接赋值。这其中在调用new分配空间得时候的时候,系统其实直接调用了类或结构的构造函数来对对其进行赋值,这个过程就相当于是string p=string("asdfgh"); 或者string p("asdfgh");(其实上面的过程还是有一定的不同之处;一 个显示式调用,一个隐式调用,两者都是在进程虚拟地址空间中的栈中分配内存,而第一种使用了new,在堆中分配了内存,而栈中内存的分配和释放是由系统管 理,而堆中内存的分配和释放必须由程序员手动释放,所以这就产生一个问题是把对象放在栈中还是放在堆中的问题,这个问题又和堆和栈本身的区别有关)    对于类和结构体这样子很方便,对一般的数据类型这样就没什么必要了。  在对这样子的分配空间进行内存释放的时候直接调用delete来释放,delete p就可以了。这个过程中,对于一般数据类型就直接释放,对于类或者结构体delete调用其析构函数类释放内存。
    • 用new来分配多块内存的时候就要使用new[]来分配,eg:char* p=new char[size];string *p=new string [size];在这个过程中new[]干了两件事,一个是记录要分配的数量size,(可以是在分配的内存前一段某个位置额外分配分配了几个字节来说储存数据来记录大小,也可以是在后台专门有一个表来记录各个数组的大小,这与内存分配器的工作方式有关。你可以以n种方式来实现这个过程,但是必须要能记录数组的大小)再向系统申请分配内存并返回数组的指针(而不是所有分配的空间的起始地址)。对于结构体或者类,new[]调用构造函数size次,其实质还是记录大小和分配空间两件事。对于用new[]分配的内存在释放的时候就必须用delete[]来释放,直接delete[] p就可以了。delete[]怎么知道要释放多大的内存或调用多少次析构函数,就是由于在new分配的时候专门特意的记录了要分配数组的大小,delete[]的时候就先读取这个值,然后调用size次析构函数来释放空间或者根据size来直接释放空间。
    • void *operator new(size_t);     //allocate an object
      void *operator delete(void *);    //free an object
      
      void *operator new[](size_t);     //allocate an array
      void *operator delete[](void *);    //free an array
      

      这是在c++11 new中对这几个函数的定义,平时可直接使用,但再次主意new[]分配的只能通过delete[]来释放,如果用delete的话这只能释放掉数组的第一项,后边的还是存在的。因为数组的地址就是数组第一项的地址。所以new[]的一定要用delete[]来释放。

    •                                                    
    • malloc与free都是c语言中的函数,malloc的返回值为void型,在使用的时候要注意对其进行类型转换,                               eg:char* p=(char*)malloc(number*sizeof(char));malloc在分配内存的时候是以字节来分配的。在分配之前也会记录数组的大小和类型。最后返回一个指向数据区的void型指针。malloc分配的内存必须通过free来释放。与malloc有关的函数还有calloc与realloc,其中calloc在分配完内存返回指针之前把所有的数据都初始化为0,相当于malloc加上memset。realloc函数可以吧原来分配的好的内存块的改变大小。动态分配的内存必须是整体一块释放,但是realloc可以缩小一小块动态分配的内存,有效的释放他尾部的部分内存。
    • 关于在调用delete或者free之后系统是否真正的释放了内存的问题。可以通过程序+任务管理器性能窗口来进行检测
      #include<stdio.h>
      #include<stdlib.h>
      #include<Windows.h>
      char*ch[1000];
      int size = 20000;
      int main()
      {
      	int i, j;
      	for (int i = 0; i < 1000; i++)
      	 ch[i] = (char*)malloc(sizeof(char)*size);
      	for (i = 0; i < 1000;i++)//换入内存,如不进行操作,glibc并不会真正的向系统申请内存
      		for (j = 0; i < size; j++)
      			ch[i][j] = ' '; 
      		Sleep(20000);//在此期间查看内存使用情况
      		for (i = 0; i < 1000; i++)
      			free(ch[i]);
      		Sleep(20000);//再次查看内存使用情况
      	return 0;
      }
      

       实验发现,free前与free后的内存使用情况是相同,并没有因为free而空闲出很多内存。而当程序跑完最后的return 0;之后内存使用率才真正的降下来。此时程序涉及到的内存才真正的被完全释放。所以答案是free并没有真正释放内存,相关内存块储存的东西仍然在,而free与delete的过程只是切断了指针与内存块的联系,这块内存本身在没有其他的数据对其进行修改的时候一直都储存着其原来的东西。有其他的内存分配需求的时候这块内存很可能就被分配过去了,然后谁想怎么改就怎么改(就类似于优盘格式化后不向里边写入新东西,原来的东西还是存在的一样)(如果分配到的内存特别特别大的话,free后有可能内存使用率直接降下来,这与操作系统内存管理有关)

    • warning:      1.不管是用new还是用malloc在进行内存分配的时候都要先检查一下是否分配到内存,分配完了之后要赶紧检查一下返回指针是否为NULL;不管是用free还是用delete或者delete[]释放完内存之后都要把原本来指针变为空指针,要不然就变成野指针了,很危险。 2.一个new对应一个delete,一个new[]对应一个delete[],一个malloc对应一个free,必须这样子。要不然会造化内存泄露。也不要对直接定义了的变量或者数组进行free或者delete;不能free一个非malloc返回的指针,不能delete一个非new返回的指针。
  • 相关阅读:
    Golang的select多路复用以及channel使用实践
    golang-goroutine和channel
    golang类型转换小总结
    golang之终端操作,文件操作
    golang之结构体和方法
    golang基础之三-字符串,时间,流程控制,函数
    Linux Keepliaved安装
    Git打标签、还原到具体标签版本代码
    Git复制已有分支到新分支开发
    记一次内存分析
  • 原文地址:https://www.cnblogs.com/freedom314/p/5027896.html
Copyright © 2020-2023  润新知