C语言动态内存分配

摘要:
2.几个内存分配函数2.1 malloc函数头文件malloc。h void*malloc(size_tsize)//-------->size参数实际上是所需字节数的整数malloc(20);否则,返回NULL(空指针)//需要无空(p);int p=(int)malloc(n*sizeof(int));

C语言动态内存分配:堆不连续 栈连续

动态内存分配:

1.从静态存储区域中分配(系统自己分配)

2.从堆内存中分配(动态内存分配)

3.在栈中进行分配(系统自己分配)

动态内存分配和释放函数:

malloc函数

calloc函数

recalloc函数

free函数

常见内存分配错误:

使用未分配的内存

引用了分配成功但尚未初始化的内存

内存分配且初始化了,但进行了越界操作

忘记释放内存,造成内存泄露

释放内存之后,继续去使用这一内存 

free之后,继续使用指针,野指针

1.内存分配方式:

1.1在静态存储区中进行分配

内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量

1.2在栈中进行分配

在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时,这些存储但愿自动被释放。效率很高,但是分配的内存容量比较有限

1.3在堆中进行分配

在堆上分配也称为动态内存分配:程序在运行的时候用malloc等函数申请任意多少的内存,程序员自己负责在何时用free释放内存。动态内存分配的生存期由我们自己决定,使用非常灵活,但是问题相对也比较多;注意://如果没有释放的话,很容易就会造成内存溢出,因为堆中的内存块是全局的,因此不会因为函数的调用而结束。

2.几个内存分配函数

2.1malloc函数 头文件malloc.h 

void *malloc(size_t size) //————–>返回的是一个通用类型的指针,根据需要去进行强转; 
功能:允许从空闲内存池中分配连续内存但不初始化 
参数:size参数实际就是一个所需字节数的整数 malloc(20); 
返回:若分配成功则返回一个指向该内存块的指针,在使用时可根据需要做强制类型转换,否则返回NULL(空指针)//需要判空 
free(p);//释放内存空间,将内存释放出来给系统; 
free函数与malloc函数是成对出现的; 
申请malloc的时候尽量去给它进行一下初始化,防止后面出现一些不确定性的东西; 
malloc的生命周期:只要没有调用free这个函数,进程没有结束,那么此时,这个函数的生命周期就会一直存在在内存中;它是存放在堆空间中的,它不会因为你去函数调用的结束自动去释放,堆当中的内存是全局的。

如:int p = (int )malloc(n*sizeof(int)); //在空闲内存池中分配连续内存n*sizeof(int)个字节的堆内存空间

#include<stdio.h>
#include<malloc.h>

void out(int *p,int n)
{
int i;
for(i=0;i<n;i++)
{
printf("%d",*(p+i));
printf("--------------- ");
}

}

int main(void)
{
printf("please input one number:");
int n;
scanf("%d",&n);
//申请
int *p = (int *)malloc(n * sizeof(int));
//内存申请成功
if(p != NULL){
out(p,n);
int i;
for(i=0;i<n;i++){
*(p+i)=i*i;
}
out(p,n);
//释放掉堆内存
free(p);
}else{
//内存申请失败
printf("malloc is NULL! ");
}
return 0;
}

C语言动态内存分配第1张

(没有初始化,堆里面的值是不确定的)

2.2calloc函数 头文件stdlib.h 

 void *colloc(size_t num_elements,size_t element_size); 
功能:功能同malloc是一样的,但是作初始化 
参数:num_elements是所需的元素的数量,element_size是每个元素的字节数 
返回:同malloc函数一样 
也是需要与free(p)进行对称使用

#include<stdio.h>
#include<stdlib.h>

int main(void)
{
printf("please input one number:");
int n;
scanf("%d",&n);
int *p = (int *)calloc(n,sizeof(int));
if(p!=NULL){
int i;
for(i=0;i<n;i++)
{
printf("%d ",*(p+i));
}
printf(" ");
free(p);
}else{
printf("calloc error ");
}
return 0;
}

C语言动态内存分配第2张

2.3realloc函数:头文件(stdlib.h),动态扩大缩小申请的内存

void *realloc(void *ptr,size_t new_size); 
功能:在指针ptr指向的内存基础上扩大或者缩小内存 
参数:ptr是指向先前通过malloc,calloc和realloc函数后分配的内存块的指针,new_size是内存块的新尺寸,可能大于或者小于原有内存尺寸;这个是追加到new_size的新的内存 
realloc在C语言中也被称为动态数组; 
realloc函数使用的注意点: 
1:当扩展内存的时候,不会对添加进内存块的字节进行初始化 
2:若不能调整内存则返回NULL,但原有内存中的数据是不会发生改变的 
3:若第一个参数为NULL那么功能 等同与malloc函数,若第二个参数为0,那么会释放调用内存块

realloc(NULL,10*size(int)) 等同malloc(10*sizeof(int));
realloc(p,0); 等同于free

4:当缩小或者扩大内存时,一般不会对其进行移动,若无法扩大内存块,那么会在别处分配新的内存快,然后把旧内存块的数据复制到新块 中,并将旧块删除释放内存;

#include<stdlib.h>
#include<stdio.h>
#include<malloc.h>
void out(int *p ,int n){
int i;
for(i = 0 ;i < n; i++){
printf("%d ",*(p+i));
}
}
int main(void)
{
//申请4个字节的堆内存空间,未初始化
int * p = (int *)malloc(5*sizeof(int));
if(p == NULL) exit(1);
*p = 1;
*(p+1) =2;
p[2] = 3;
p[3] = 4;
p[4] = 5;
out(p,5);
printf("=============== ");
//追加申请10个字节的内存空间,追加的空间也是未进行初始化的
p = (int *)realloc(p,10*sizeof(int));
if(p == NULL) exit(1);
p[6] = 6;
*(p+6) = 7;
*(p+7) = 8;
*(p+8) = 9;
*(p+9) = 10;
out(p,10);
free(p);
//free之后,将指针置为空
p = NULL;
return 0;
}

C语言动态内存分配第3张

2.4free函数 

free之后如果还有这块内存地址的话,此时这块内存归还给了系统,(可能这块内存还处于一个空闲状态)但是还是可以对其进行操作。里面的值短暂的会保留。 
free之后,申请内存的那个指针就会变成野指针(声明了,但是没有任何指向的指针),有时候会出现野指针错误; 
所以尽量在操作之后:将指针置为NULL 
p=NULL; 
注意:申请和释放是成对的,所以程序是不能进行多次free的,否则会崩溃的

常见的内存错误:

1:段错误 
使用未分配成功的内存 
避免方式:在使用内存之前检查指针是否为NULL; 
引用分配成功但尚未初始化的内存 
避免方式:赋予初值,即便是赋予零值也不可省略 
内存分配成功并且已经初始化,但操作越过了内存的边界 
避免:注意下表的使用不能超出边界 
忘记释放内存,造成内存泄露 
避免方式:申请内存的方式和释放内存的方式需要成双成对 
释放内存之后却继续去使用这一块内存 
避免方式:使用free内存之后,把指针置为NULL;

内存错误的注意点: 
指针消亡了,并不表示它所指向的内存会被自动释放,(在free之前,直接将指针设为NULL); 
内存释放了,并不代表指针会消亡或者成了NULL指针;(在free之后,指针并没有进行NULL设置)

野指针: 
野指针的形成是指针变量没有被初始化,任何指针变量刚被创建的时候不会自动成为NULL指针,它的缺省值是最忌的,它会乱指一气

指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法内存

free内存块之后,需要将指针设置为NULL,如果没有设置为NULL,也会出现“野指针”,它是指向“垃圾”内存的指针;

多次free内存块,是会导致程序崩溃的

免责声明:文章转载自《C语言动态内存分配》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇python的整数没有补码一说如何实现在H5里调起高德地图APP?下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

《自拍教程45》Python adb实时监控Logcat日志

接上一篇:adb命令_一键截取logcat日志, 有一天, 系统稳定性开发负责人找到我,希望我能在跑android 系统monkey的时候, 实时监控logcat的输出,如果一旦发现“java.lang.NullPointerException"空指针异常, 则立刻用adb bugreport命令导出当时log压缩包出来。 准备阶段 adb logcat...

PCRE正则库的使用

使用pcre编写C或C++程序,然后编译。 对于C程序,编译命令为:gcc -I/usr/local/include/pcre -L/usr/local/lib/pcre -lpcre file.c 对于C程序,编译命令为:gcc -I/usr/local/include/pcre -L/usr/local/lib/pcre -lpcrecpp file....

【javascript】浅析js中的堆和栈

这里先说两个概念:1、堆(heap)2、栈(stack)堆 是堆内存的简称。栈 是栈内存的简称。说到堆栈,我们讲的就是内存的使用和分配了,没有寄存器的事,也没有硬盘的事。各种语言在处理堆栈的原理上都大同小异。堆是动态分配内存,内存大小不一,也不会自动释放。栈是自动分配相对固定大小的内存空间,并由系统自动释放。 javascript的基本类型就5种:Unde...

VIM使用系列之一——配置VIM下C/C++编程环境

作者:gnuhpc from http://blog.csdn.net/gnuhpc本文环境:ubuntu 9.10 1.基本配置建立三个目录:mkdir ~/.vim/{plugin,doc,syntax} –p建立配置文件:touch ~/.vimrc vimrc作为vim的主要配置文件,我们在配置VIM时首先对它进行基本的设置。打开你home目录下的...

Python有返回值的函数_布尔函数

函数也可以返回布尔值(True或False),这种情况便于隐藏函数内部的复杂测试。例如: #!/bin/python def is_divisible(x, y):     if x % y == 0:        return True     else:        return False print is_divisible(6, 3) $...

用句柄操作下拉框

你要获得组合框的句柄做什么呢?是要读取组合框条目的值还是进行什么操作呢?要读取值用selectedIndex读取索引值(从0开始),用selectedItem读取选项的内容(要进行类型转换),用selectedIndex.key可以获得按键值;要完成句柄的操作也有三种方式,用其一也可,但工程较大,用于Windows编程:1、用父窗口的函数: WM_DRAW...