目录
一、内存管理
内存:
1、栈区(stack)
编译器自动分配。在函数调用时,第一个进栈的是主函数中函数调用后的下一条指令的地址,然后是函数的各个参数;函数调用结束后,内存释放。
注:若想从函数中返回局部变量的地址(指针),应将该局部变量设为静态局部变量,此时它存在静态区,不会随着栈区内存释放而被释放。
2、堆区(heap)
由程序员分配和释放。
函数 | 作用 |
---|---|
void *malloc(int num); | 在堆区分配一块指定大小的内存空间,这块内存空间在函数执行完成后不会被初始化,它们的值是未知的。malloc比calloc更高效。 |
void *calloc(int num, int size); | 在堆区中动态地分配 num 个长度为 size 的连续空间,并将每一个字节都初始化为 0。写零操作大部分时候不需要。 |
void *realloc(void *address, int newsize); | 该函数重新分配内存,把内存扩展到 newsize。 |
void free(void *address); | 该函数释放 address 所指向的内存块,释放的是动态分配的内存空间。 |
动态分配内存,重新调整内存大小与释放内存:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char name[100];
char *description;
strcpy(name, "Zara Ali");
/* 动态分配内存 */
description = (char *)malloc( 30 * sizeof(char) );
//将(void *)强制转换为(char *)
//description = (char *)calloc( 30, sizeof(char) );
if( description == NULL )
{
fprintf(stderr, "Error - unable to allocate required memory\n");
}
else
{
strcpy( description, "Zara ali a DPS student.");
}
/* 假设您想要存储更大的描述信息 */
description = (char *) realloc( description, 100 * sizeof(char) );
if( description == NULL )
{
fprintf(stderr, "Error - unable to allocate required memory\n");
}
else
{
strcat( description, "She is in class 10th");
}
printf("Name = %s\n", name );
printf("Description: %s\n", description );
/* 使用 free() 函数释放内存 */
free(description);
/* 指针置为空指针 */
description = NULL;
}
输出结果
Name = Zara Ali
Description: Zara ali a DPS student.She is in class 10th
3、有关复制、初始化的函数
函数 | 作用 | 注意 |
---|---|---|
strcpy(dest, src) | 把src 所指由\0 结束的字符串复制到dest 所指的数组中。 | 二者所指内存区域不能重合,dest内存>src内存。 |
memcpy(dest, src, count) | 由src 所指内存区域复制count个字节到dest 所指内存区域。 | 二者所指内存区域不能重合,一定会复制count个字节。 |
memmove(dest, src, count) | 由src所指内存区域复制count个字节到dest 所指内存区域。 | 二者所指内存区域可以重合,拷贝结果一定正确。 |
memset(dest, c, count) | 将已开辟内存空间dest的首count个字节的值设为值c,并返回dest。 | 常用于內存空间的初始化。 |
4、内存泄漏(Memory Leak)
指程序中已动态分配的堆內存由于某种原因程序未释放或无法释放,造成系统內存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
5、内存池
内存碎片:
内存碎片一般是由于空闲的內存空间比要连续申请的空间小,导致这些小内存块不能被充分的利用,当你需要分配大的连续内存时,尽管剩余内存的总和足够,但系统找不到连续的内存,所以导致分配失败malloc/free大量使用会造成内存碎片。
为什么会产生内存碎片?
如果有100个单位的连续空闲内存,那么先申请5单元的连续内存,再申请50单元的内存,这时释放一开始的5单元的内存。而如果你一直申请比5单元大的内存单元,那么开始的那连续的5单元就一直不能被使用。
内存池技术:
内存的申请、释放是低效的,我们只在开始申请一块大內存(不够继续申请),然后每次需要时都从这块内存取出,并标记这块内存是否被使用。释放时仅仅标记而不真的free,只有内存都空闲的时候,才释放给操作系统。这样减少了 malloc、free次数,从而提高效率。