博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
指针的动态初始化malloc与销毁free
阅读量:4302 次
发布时间:2019-05-27

本文共 5659 字,大约阅读时间需要 18 分钟。

指针动态初始化:

int *p = (int*)malloc(sizeof(int)*3);//初始化为指向3个元素的数组

if(!p) exit -1;//这个地方一定要进行判断,因为若动态初始化不成功,在使用p[0]、p[1]、p[2]时报错。
指针的销毁:

free(p);

p = NULL;//避免p为野指针,需要赋值为NULL
         //p中的值仍为原先的内存地址,此时要进行赋值NULL。
         //释放内存后,赋值为NULL的好处还有:当p为NULL时,即便再free n次也不会出错!!!
注意:free的含义:free之后,是将由malloc分配的内存交还给系统支配,而代码支配不了了,即由malloc分配的内存中内容由系统进行处理。

其中存在两个值:一个是指针的值,指针的值并未发生改变,还是原先指向malloc分配的地址。

另一个是malloc分配的内存值,这其中的值取决于系统有没有使用该内存,如果使用了,该内存中的值会发生改变,如果没有使用,则还是保持原先的值。

总结:

初始化要判断内存是否申请成功;
销毁时要赋值NULL 。
//************************

1、变量内存的动态分配(创建)与释放:通过指针,动态间接赋值、取值

指针变量名=new 数据类型(初始值); 初始值可省略,后边再赋值。

delete 指针变量名;

复制代码

#include
using namespace std;int main() { //int *p = new int; *p = 5; int *p = new int(5);//new运算符,动态创建一个int型变量(无变量名),值为5。 cout << *p;//输出所指地址的值 delete p;//释放指针变量的内存空间 return 0;}

复制代码

2、一维数组的动态分配(创建)与释放:

指针变量名=new 数据类型[正整数常量、变量或表达式];

delete [ ]指针变量名;

复制代码

#include
using namespace std;int main() { int *p = new int[5];//new运算符,动态创建一个int型数组(无数组名)。 *(p + 1) = 10;//赋值第2个元素 //或p[1]=10; cout << p[1];//输出所指地址的值 delete []p;//释放指针变量数组的内存空间 return 0;}

复制代码

显示Fibonacci数列的前N项,0,1,1,2,3,5,8,…

复制代码

#include
using namespace std;int main() { int N; cin >> N; int *p = new int[N]; //动态创建包含N个元素的数组 p[0] = 0; p[1] = 1;//给定第1、2元素的值,等效*p=0;*(p+1)=1; for (int i = 2; i < N; i++){ p[i] = p[i - 1] + p[i - 2]; } for (int i = 0; i < N; i++) { cout << p[i] << " "; } delete []p;//释放指针变量数组的内存空间 return 0;}

复制代码

//************************

什么是动态内存的申请和释放?
 
当程序运行到需要一个动态变量时,需要向系统的堆中申请一块内存,用来存储这块变量,这就是内存的申请。当程序不需要这个变量时,就需要把申请的这块内存释放掉,这就是内存的释放。往往内存的申请和释放是一起使用的,只要有内存的申请,就要有内存的释放,避免出现内存泄漏。
 
C语言指针的申请:
 
(1).在C语言中使用malloc函数申请内存,函数原形: 
void* malloc(size_t size);
参数size代表申请的内存的字节数,参数size_t代表指针的类型,比如int char或者是结构体的类型。如果内 存申请成功返回内存的首地址,如果申请失败,返回NULL(注意NULL全部大写)
 
(2).在使用该函数的过程中,需要注意以下几点:
 
1.该函数的参数很简单,只是申请内存的大小,单位是字节
2.申请内存后,必须要检查是否内存分配成功。
3.申请到的内存是一块连续的内存,该函数和free()函数配对使用。
4.虽然该函数的类型是(void*),但是在使用时还是建议进行强制类型转换
  
(3).内存申请的例子:
 
char *P = NULL;(给指针初始化,防止出现野指针)
 
P = (char *)malloc(10 * sizeof(char));  
 
if(P == NULL){
exit(1);
}else{
gets(P);
}
 
 
C语言指针的释放:
 
(1).在C语言中使用free函数释放内存,函数原形:
void free(void *ptr);
 
参数ptr代表内存的首地址,该函数没有返回值。
 
(2).在使用该函数的过程中,需要注意以下几点:
1.该函数释放的是指针指向的内存,释放的是内存,不是指针。释放内存后指针要指向NULL
2.和malloc函数配对使用,内存申请后要记得释放,避免内存泄漏。
3.不允许重复释放。
 
(3).内存释放的例子:
 
if(P != NULL){
free(P);
P = NULL; //指针释放之后并不为空,要设置其为空。
}
 
 
注意:
 
1.free()函数只能释放堆空间,堆是大家共有的空间,分局部堆和全局堆,全局堆是没有分配的空间,局部堆是用户分配的空间。用过堆的内存之后要记得还给系统,不然容易发生内存泄漏。
 
2.栈是线程独有的,每个线程的栈都是互相独立的,每个函数都有自己的栈,栈被用来在函数之间传递参数。像代码区,静态变量,全局变量,栈区上的变量都是不需要程序员进行释放的。(这些区域上的空间,不能用free()函数释放)
 
3.野指针:野指针指的是指向“垃圾”内存的指针,不是NULL指针。出现野指针主要有以下几个原因:
      ①.指针没有初始化(指针如果没有初始化,值是不确定的。也就是说,没有初始化的指针,指向的是垃圾内存,非常危险。)
      ②.指针free之后,没有设置为NULL。
      ③.指针超越了变量的作用范围。指针操作时由于逻辑上的疏忽,导致指针访问了非法内存,这种情况是非常容易出现的。
      ④.不要返回指向栈内存的指针。
//***************************

主要初步介绍malloc、free、calloc、realloc的基本。日后会有更详细的内容。

malloc、free分别用于动态内存分配和释放。

malloc会从内存池里提取一块合适的内存(连续的),并返回指向这块内存(起始位置的指针,该指针的类型为void*指针(因为malloc不知道你请求的内存需要存储的数据类型),而且这块内存并没有初始化。

如果操作系统无法提供给malloc足够的内存,malloc就会返回一个NULL指针。因此必须对每个从malloc返回的指针进行检查。

复制代码

 1 #include <stdio.h>

 2 #include <stdlib.h>
 3 
 4 int main() 
 5 {
 6     int *pi;
 7     int i;
 8     pi = malloc(25 * sizeof( int ));
 9     
10     if( pi == NULL )
11     {
12     printf( "Out of memory!\n" );
13     exit(1);
14     }
15     
16     for(i = 0; i != 25; i++)
17         pi[i] = i;
18 
19     for(i = 0; i != 25; i++)
20         printf("%d ", pi[i]);
21     printf("\n");
22 
23     return 0;

复制代码

24 } 

 

calloc也可以用于内存分配,但是返回指向内存的指针之前会初始化为0。而且calloc和malloc请求内存数量的方式也不一样。

realloc用于修改一个原先已经分配的内存大小。PS:若原来的内存块无法改变大小,realloc将分配另一块正确的小的内存,并把原来的那块内存的内容复制到新的内存块。

free函数的参数为一个先前从malloc、calloc、realloc返回的值。对NULL指针不会产生任何效果。

 

动态内存分配最常见的错误是忘记检查请求的内存是否分配成功。

《C与指针》里面提供了一个程序可以减少错误的内存分配器。

代码如下:

1 #include <stdlib.h>

3 #define malloc  //用于防止由于其他代码块直接塞入程序而导致偶尔直接调用malloc
4 #define MALLOC(num, type) (type *)alloc((num) * sizeof(type))//接受元素的数目和类型,调用alloc函数获得内存,alloc调用malloc并进行检查,确保返回的指针不是NULL

5 extern void *alloc( size_t size ); 

复制代码

 1 #include <stdio.h>

 2 #include "alloc.h"
 3 #undef malloc
 4 
 5 void *alloc( size_t size )
 6 {
 7     void *new_mem;
 8     /*
 9      * 请求所需的内存,并检查是否分配成功
10      */
11     new_mem = malloc( size );
12     if( new_mem == NULL )
13     {
14         printf("Out of memory!\n" );
15         exit(1);
16     }
17     return new_mem;

复制代码

18 } 

  1 #include <stdio.h>

复制代码

 2 #include "alloc.h"

 3 
 4 int main()
 5 {
 6     int *new_memory;
 7     int i;
 8 
 9     /*
10      * 获得一个整型数组
11      */
12     new_memory = MALLOC( 25, int );
13     
14     for(i = 0; i != 25; i++)
15         new_memory[i] = i;
16 
17     for(i = 0; i != 25; i++)
18         printf("%d ", new_memory[i]);
19     printf("\n");
20     return 0;
21 }

复制代码

//***************************

关于malloc申请内存的函数

一、定义
malloc函数是一种分配长度为num_bytes字节的内存块的函数,可以向系统申请分配指定size个字节的内存空间。malloc的全称是memory allocation,中文叫动态内存分配,
函数返回的类型是void*类型。void*表示未确定的类型。

C,C++规定,void* 类型可以通过类型转换强制转换为任何其它类型的指针。

二、函数声明与使用

头文件
#include <stdlib.h>
或者
#include <malloc.h>

void *malloc(size_t size);

备注:void* 表示未确定类型的指针,void *可以指向任何类型的数据,更明确的说是指申请内存空间时还不知道用户是用这段空间来存储什么类型的数据(比如是char还是int或者其他数据类型)。

三、与new的区别

1)从本质上来说,malloc(Linux上具体实现可以参考man malloc,glibc通过brk()&mmap()实现)是libc里面实现的一个函数,如果在source code中没有直接或者间接include过stdlib.h,那么gcc就会报出error:‘malloc’ was not declared in this scope。如果生成了目标文件(假定动态链接malloc),如果运行平台上没有libc(Linux平台,手动指定LD_LIBRARY_PATH到一个空目录即可),或者libc中没有malloc函数,那么会在运行时(Run-time)出错。new则不然,是c++的关键字,它本身不是函数。new不依赖于头文件,c++编译器就可以把new编译成目标代码(g++4.6.3会向目标中插入_Znwm这个函数,另外,编译器还会根据参数的类型,插入相应的构造函数)。

2)在使用上来说
   
   1、new 返回指定类型的指针,并且可以自动计算所需要大小 

int *p;

p = new int;//返回类型为int *类型(整数型指针),分配大小为sizeof(int);
   

而 malloc 则必须要由我们计算字节数,并且在返回后强行转换为实际类型的指针。

int *p;
p = (int*)malloc(sizeof(int) * 128);//分配128个(可根据实际需要替换该数值)整型存储单元,//并将这128个连续的整型存储单元的首地址存储到指针变量p中
double *pd = (double*)malloc(sizeof(double) * 12);//分配12个double型存储单元,//并将首地址存储到指针变量pd中

  2、另外有一点不能直接看出的区别是,malloc 只管分配内存,并不能对所得的内存进行初始化,所以得到的一片新内存中,其值将是随机的。所以malloc的内存要首先进行初始化
 

 

转载地址:http://ogows.baihongyu.com/

你可能感兴趣的文章
期货市场技术分析02_趋势的基本概念
查看>>
期货市场技术分析03_主要反转形态
查看>>
期货市场技术分析04_持续形态
查看>>
期货市场技术分析05_交易量和持仓兴趣
查看>>
TB交易开拓者入门教程
查看>>
TB创建公式应用dll失败 请检查用户权限,终极解决方案
查看>>
python绘制k线图(蜡烛图)报错 No module named 'matplotlib.finance
查看>>
talib均线大全
查看>>
期货市场技术分析06_长期图表和商品指数
查看>>
期货市场技术分析07_摆动指数和相反意见理论
查看>>
满屏的指标?删了吧,手把手教你裸 K 交易!
查看>>
不吹不黑 | 聊聊为什么要用99%精度的数据回测
查看>>
X 分钟速成 Python
查看>>
对于模拟交易所引发的思考
查看>>
高频交易的几种策略
查看>>
量化策略回测TRIXKDJ
查看>>
量化策略回测唐安奇通道
查看>>
CTA策略如何过滤部分震荡行情?
查看>>
量化策略回测DualThrust
查看>>
量化策略回测BoolC
查看>>