内存管理
进程空间
源程序:源代码
程序(可执行文件):有源程序编译后的文件
进程:时间概念,可执行文件被拉起到结束的这段过程。进程可以被拉起多个。
进程空间:可执行文件被拉起,在内存中的分布情况。
进程空间的分布:
stack
heap
data
>未初始化
>初始化
text
32位机最大寻址3G,
重点栈,堆
栈:auto修饰的变量,谁调谁用,用完即消。不需要人工干预。(入栈与出栈的关系),栈溢出。主要用于数据的交换,为不是适用于大空间的申请使用(大数据的申请用堆)
。大小不超过10M,避免大量的递归。
发展方向:由高到低先定义的在高位上,后申明的在低位上。
堆:可以存放任意类型的数据类型,但需要自己申请使用与释放。
申请:malloc();
释放:free();
大小:大空间。
发展方向:由低到高
char * p = (char*)molloc(1024*1024*1024);//加内存可解决
strcpy(p,"adbksj");
printf("sjdkjfk");
free(p);
申请mallloc以字节为大小
基本类型的申请
int * p = (int*)malloc(1*sizeof(int));//申请int类型的4个字节的大小
*p = 100;//初始化
printf("*p = %d\n",*p);//100
构造类型--数组的申请:
申请和初始化的最小单位均是字节
memset(p,0,sizeof(int))初始化
int arr[10];
int *p = (int*)malloc(10*sizeof(int));
memset(p,0,10*sizeof(int));//初始化,p:首地址,0:初始化元素,后面是大小
for(int i = 0;i < 10;i++) {
printf("%d\n",p[i]);//不知道的值,不能使用*p++
}
free(p);
calloc()
int *p = (int *)calloc(10,sizeof(int));//10个4个单元的大小
for(int i = 0;i < 10;i++) {
printf("%d\n",p[i]);//自动初始化了
}
realloc()扩容
char * pa = (char*)malloc(10);
strcpy(pa,"1234567890abcdef");//实际数据大于了申请的空间,这时候使用realloc();
char *pa = (char*)malloc(10);
char *newPa;
newPa = realloc(pa,20);
strcpy(newPa,"1234567890abcdef");
//newPa与pa有时候会不一样
free(newPa);
或者
char *pa = (char*)malloc(10);
pa = realloc(pa,20);
strcpy(pa,"1234567890abcdef");
//newPa与pa有时候会不一样
free(pa);
realloc()有两种情况,一种是空间不足在后买你继续扩充,另一种是开辟的空间不足,重新开辟足够的空间,把数据复制过去。
应用模型
#include<stdio.h>
#include<stdlib.h>
int main() {
int *pa;
int len;
printf("please new len:");
scanf("%d",&len);
pa = (int*)malloc(len*sizeof(int));
int oldlen = len;
for(int i = 0;i<len;i++) {
pa[i] = 100+i;
printf("%d\n",pa[i]);
}
printf("please large len:");
scanf("%d",&len);
pa = (int*)realloc(pa,len*sizeof(int));
for(int i = 0;i<len;i++) {
if(oldlen <= i)
pa[i] = 200+i;
printf("%d\n",pa[i]);
}
printf("please small large len:");
scanf("%d",&len);
pa = (int*)realloc(pa,len*sizeof(int));
for(int i = 0;i<len;i++) {
printf("%d\n",pa[i]);
}
free(pa);
return 0;
}
常见问题解析
错误模型一:在服务器模型中,常用到大循环,在大循环中未释放原有空间,重新申请新空间,造成原有空间内存泄漏。
while(1) {
char *pa = (char*)malloc(100);
printf("ooooooooooooo\n");
printf("ooooooooooooo\n");
printf("ooooooooooooo\n");
printf("ooooooooooooo\n");
printf("ooooooooooooo\n");
printf("ooooooooooooo\n");
printf("ooooooooooooo\n");
printf("ooooooooooooo\n");
printf("ooooooooooooo\n");
printf("ooooooooooooo\n");
printf("ooooooooooooo\n");
printf("ooooooooooooo\n");
printf("ooooooooooooo\n");
printf("ooooooooooooo\n");
pa = (char*)malloc(100);//前面申请之后没有释放,重新申请
//第一次申请,没有释放,在内存中占有空间,第二次给同一变量再次申请,前一次的空间没有释放。同样占有内存空间。释放要配对使用。两次使用free();也会挂机。malloc多余free会挂机,free对于malloc也会挂机。
}
置空与判空
对内存使用的逻辑:申请,判空,使用,释放,常见错误:释放以后未置空为NULL再次做判空使用或者释放以后继续菲方使用。
char *pc = (char*)malloc(100);//申请
if(pc == NULL) {
printf("error\n");//内存里已经没有空间了
exit(-1);
}
strcpy(px,"afakjfklajflkfja");//使用
free(pc);//释放
pc = NULL;//置空
谁申请谁释放,防止多次释放
void func(char*p) {
printf("%s\n",p);
free(p);
p = NULL;
}
int main() {
char *p = (char*)malloc(100);
if(NULL == p) {
exit(-1);
}
strcpy(p,"adajsfkljlk");
func(p);
free(p);
p = NULL;
//会挂机,func中无需释放,谁申请谁释放
return 0;
}
开放的地址空间
void foo() {
printf("p = %s\n",p);
}
void func() {
printf("p = %s\n",p);
}
int main() {
char *p = (char*)malloc(100);
strcpy(p,"afkajfklj");
func(p);
foo(p);
return 0;
}
//p属于同一个变量,但是属于不同空间。p地址在不同的作用域中是共同开放的。
堆与栈空间的返回
栈空间不可以返回,堆空间可以返回。
1.只可以返回
2.地址也可以返回,返回来的地址不要去使用
3.谁用谁开,用完即消,不可以返回----栈
4.堆上的空间是可以返回的
int func() {
int a = 500;
return a;
}
int* foo() {
int a = 500;
/*
printf("&a = %p\n",pa);windows下不行
*/
int *pa = &a;
printf("&a = %p\n",pa);
return pa;
}
int *func2() {//谁用谁开,用完即消,不可以返回----栈
int arr[100];
return arr;
}
int main() {
int a = func();//可以返回
printf("a = %d\n",a);
int *pa = foo();//地址可以返回,空间消失了。
printf("pa = %p\n",pa);
return 0;
}
堆的返回
char * getFormatMem(int size,char content) {
char *p = (char*)malloc(size*sizeof(char));
if(NULL == p)
exit(-1);
memset(p,content,size*sizeof(char)-1);
p[size*sizeof(char)-1] = ‘\0‘;
return p;
}
int main() {
char *p = getFormatMem(100,‘a‘);//包装好的申请
printf("p = %s\n",p);
free(p);//释放,
return 0;
}
原文地址:https://www.cnblogs.com/intelwisd/p/8326020.html
时间: 2024-11-06 11:25:46