C内存管理

堆内存与栈内存:

栈:

它是采一种栈结构(先进后出)的方式管理内存,它的申请和释放归操作系统管理。
栈内存的大小有限,不适合保存大量数据。
栈内存可以与标识符建立联系(定义变量)。
栈内存不适合长久保存数据(当函数结束后它就会被释放)。
栈内存归操作系统管理,几乎不会出现什么错误。
栈内存使用方便,随时定义、使用、释放。

堆:

数据无序的顺序存储在内存中,它的申请和释放受程序员的控制。
堆内存的大小理论上等于物理内存的大小。
堆内存只能与指针配合使用(无法取名字)。
堆内存的释放是受控制的,一般程序中长期使用的数据都会从数据库、文件中读取到堆内存中。
堆内存归程序员管理,如果程序员的水平有限可能会出现内存泄漏、碎片等问题。
堆内存使用麻烦,需要借助标准库函数(头文件),申请(计算大小)、使用(与指针配合)、释放(不能重复放、指针要置空)。

堆内存管理:

C语言中没有提供管理内存的语句,只能依靠标准库中提供的函数来对堆进行申请和释放。
void* 类型的指针可以为任何类型的指针互相赋值(在C++中不可以)。
#include <stdlib.h>
void* malloc(size_t size);
功能:从堆内存申请存储空间。
size:所申请的内存大小,以字节为单位。
返回值:申请到内存的首地址,如果返回人NULL表示出错。
注意:所申请到的内存的内容是不确定的,但大部情况下是0;
类型* p = malloc(sizeof(类型)*数量);

void free(void *ptr);
功能:释放从堆中申请到的内存(只是把使用全回收,内容还在,但可能会有一些细微的修改)。
ptr:要释放的内存的首地址(申请时的大小被malloc记录了下来)。

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
int main()
{
	int* const p = malloc(sizeof(int)*10);//申请空间
 	for(int i=0; i<10; i++)
 	{
  		p[i] = ~0;
  		printf("%d\n",p[i]);
 	}
	free(p);//释放内存
}

void *calloc(size_t nmemb, size_t size);
功能:从堆内存申请内存,会把申请的内存初始化。
nmemb:申请的次数
size:每次申请的字节数
返回值:申请到内存的首地址,如果返回人NULL表示出错。
注意:效率没有malloc高,大多数情况下不需要对内存初始化。

void *realloc(void *ptr, size_t size);
功能:把已经申请到的内存调在或调小
ptr:需要被调整大小的内存首地址
size:调整后大小
返回值:调整后的内存的首地址

#include <stdio.h>
#include <stdlib.h>
int main()
{
	int* p = calloc(10,4);
 	for(int i=0; i<10; i++)
 	{
  		p[i] = i;
  		printf("%d\n",p[i]);
 	}
 	malloc(8);
 	printf("%p\n",p);
 	p = realloc(p,80);
 	printf("%p\n",p);
 	for(int i=0; i<20; i++)
 	{
  		printf("%d\n",p[i]);
 	}
}

内存清理:
#include <strings.h>
void bzero(void *s, size_t n);
功能:把内存的内存设置为0
s:内存的首地址
n:要设置的字节数

#include <string.h>
void *memset(void *s, int c, size_t n);
功能:把内存以字节为单位设置为指定的值。
s:要设置的内存的首地址
c:要设置的值
n:设置设置的字节数
返回值:设置后的内存首地址(为什么会有返回值)。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
	int* p = malloc(40);
	memset(p,1,40);
	for(int i=0; i<10; i++)
 	{
  		printf("%d\n",p[i]);
 	}
 }
内存泄漏:

在程序运行期间由于管理失误导致内存无法被释放,这种情况叫作内存泄漏(当一个程序结束后,属于它的所有资源都会释放,包括泄漏的内存,但有些程序不能停止 )。
如何防止内存泄漏:
1、指针不轻易改变指向的位置(类型* const p)。
2、写完申请内存的语句,要立即写释放内存的语句(谁申请,谁释放)。
3、要保证内存释放语句初始执行。
如果出现内存泄漏怎么办:
GDB调试、打断点,监控程序的行为。

内存碎片:
已经被释放了,但无法继续使用的内存叫内存碎片(在程序运行过程中由于频繁的申请、释放小块的内存,导致一些内存虽然被释放但不能形成连续的大块内存而导致无法使用)。
内存碎片归根结底是由于释放时间与申请时间不协调造成的,因此不可能完全消除(只能尽量减少),有时候也会自动修复。
1、不要频繁的申请和释放内存。
2、尽量申请大块的连接的内存。
3、优先选择栈内存存储数据。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值