C/C++(内存管理)

内存管理

进程空间

源程序:源代码
程序(可执行文件):有源程序编译后的文件
进程:时间概念,可执行文件被拉起到结束的这段过程。进程可以被拉起多个。
进程空间:可执行文件被拉起,在内存中的分布情况。
进程空间的分布:

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
",*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
",p[i]);//不知道的值,不能使用*p++
}
free(p);

calloc()

int *p = (int *)calloc(10,sizeof(int));//10个4个单元的大小
for(int i = 0;i < 10;i++) {
    printf("%d
",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
",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
",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
",pa[i]);
    }
    free(pa);

    return 0;
}

常见问题解析

错误模型一:在服务器模型中,常用到大循环,在大循环中未释放原有空间,重新申请新空间,造成原有空间内存泄漏。

while(1) {
    char *pa = (char*)malloc(100);
    printf("ooooooooooooo
");
    printf("ooooooooooooo
");
    printf("ooooooooooooo
");
    printf("ooooooooooooo
");
    printf("ooooooooooooo
");
    printf("ooooooooooooo
");
    printf("ooooooooooooo
");
    printf("ooooooooooooo
");
    printf("ooooooooooooo
");
    printf("ooooooooooooo
");
    printf("ooooooooooooo
");
    printf("ooooooooooooo
");
    printf("ooooooooooooo
");
    printf("ooooooooooooo
");
    pa = (char*)malloc(100);//前面申请之后没有释放,重新申请
    //第一次申请,没有释放,在内存中占有空间,第二次给同一变量再次申请,前一次的空间没有释放。同样占有内存空间。释放要配对使用。两次使用free();也会挂机。malloc多余free会挂机,free对于malloc也会挂机。
}

置空与判空

对内存使用的逻辑:申请,判空,使用,释放,常见错误:释放以后未置空为NULL再次做判空使用或者释放以后继续菲方使用。

char *pc = (char*)malloc(100);//申请
if(pc == NULL) {
    printf("error
");//内存里已经没有空间了
    exit(-1);
}
strcpy(px,"afakjfklajflkfja");//使用
free(pc);//释放
pc = NULL;//置空

谁申请谁释放,防止多次释放

void func(char*p) {
    printf("%s
",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
",p);
}
void func() {
    printf("p = %s
",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
",pa);windows下不行
    */
    int *pa = &a;
    printf("&a = %p
",pa);

    return pa;
}
int *func2() {//谁用谁开,用完即消,不可以返回----栈
    int arr[100];
    return arr;
}
int main() {
    int a = func();//可以返回
    printf("a = %d
",a);

    int *pa = foo();//地址可以返回,空间消失了。
    printf("pa = %p
",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] = '';

    return p;
}
int main() {
    char *p = getFormatMem(100,'a');//包装好的申请
    printf("p = %s
",p);
    free(p);//释放,

    return 0;
}
原文地址:https://www.cnblogs.com/intelwisd/p/8326020.html