现在的位置: 首页 > 综合 > 正文

C语言内存分配

2013年11月20日 ⁄ 综合 ⁄ 共 1819字 ⁄ 字号 评论关闭

 1 ,先来一张内存分配图:

主要的内存模型和Java的差不多。参考 http://blog.csdn.net/hadoopx/article/details/9123903 之前写的一篇 java的内存分析。

2 ,对几个内存分配函数的理解。

1,malloc和calloc函数 

功能:动态内存分配函数

头文件:#include<stdio.h>

原型:void * malloc(size_t size);

    void * calloc ( size_t num,size_t size  );  //size 分配内存的大小,num 分配内存的块数。

    返回值:成功返回分配内存的首地址,失败返回null;

区别:malloc 和calloc 都可以进行内存的分配,但malloc 只能一次分配一块内存,而且不初始化所开辟的内存区,

 calloc可以开辟连续的内存,并且把所开辟的内存区初始化为数字0。

void testmalloc()
{
    //p指针在栈里面
    //malloc(sizeof(int))开辟的内存在堆里面
    //malloc没有对开辟的内存进行清0处理
    int *p  = malloc(sizeof(int));//如果不释放:导致内存泄露 p指向开辟内存的首地址。
    if(p!=NULL){//保证p在指向一块开辟成功的堆内存
        *p=123;
        printf("*p = %d",*p);
        
        free(p);
        
        p=NULL;//导致野指针的问题

    }
    else
    {  
        exit(1);
    }
}

void testcalloc(){
   //  int t[5]
   //开辟一块连续的内存,相当于数组。
   //对开辟的内存进行清0的处理,可能有上一次遗留的垃圾值。
    int *p = calloc(5, sizeof(int));//4*5 20字节
    
    if(p!=NULL){
//        for (int i = 0; i<5; i++) {
//            *(p+i) = i+2;
//        }
        for (int i = 0; i<5; i++) {
            printf("t[] = %d \n",*(p+i));
        }
        free(p);
        p=NULL;
        
        
    }else{
        exit(1);
    }
    
}

2。free函数

功能:释放内存。

头文件:#include<stdlib.h>

函数原型:void free(void *ptr);

参数 :ptr是使用malloccalloc 等内存分配函数所返回的内存首字节地址

返回值 :

free和野指针的问题:

指针被free之后,没有设置为NULL,让人误认为p是个合法指针,别看已经free了,他只是释放了他所指向的堆内存的空间。

而自己依然存在(如果没有超过在所在的函数体),通常会用if(P!=NULL)进行预防处理。

但是没有什么效果,因为p不是空指针,但也不指向合法的内存。

要解决这个问题,再free之后,直接把free的指针设为null;

3,reallco函数

 功能:更改已经配置的内存空间,即更改由malloc()函数分配的内存空间的大小。

 原型:realloc(void * ptr, size_t size);

如果分配的内存减少,realloc仅仅是返回原指针。

如果size=0, 则是等价于释放内存

如果内存扩大,

1),如果当前内存后面又需要的内存空间,则直接扩展这段内存空间,realloc返回原指针。

2) ,如果当前内存段后面的空闲字节不够,重新找一块能满足这个要求的内存块,将原数据copy到这块内存。并将原来的释放的,返回新的内存块地址。

3), 申请失败,返回null ,原来的指针仍然有效。

void testrealoc()
{
    int *p1 = malloc(5*sizeof(int)); //20个字节开辟一块连续的内存,相当于数组。但是不清零。开多少用多少,不能越界。发生系统崩溃。
    if(p1!=NULL){
        for (int i = 0; i<5; i++) {
            *(p1+i) = i+2;
        }
        
       
      int *p2 = realloc(p1, 10);//10个int类型,40字节。把p1前20个字节copy到前5个int中。

        //对后面的五个int 进行初始化
        for (int i = 5; i<10; i++) {
            printf("i = %d \n",i);
            *(p2+i) = i+5;
        }
        
        for (int i = 0; i<10; i++) {
            printf("p2 = %d \n",*(p2+i));
        }
        free(p2);
        p1 = NULL;
        p2 = NULL;
        
        
        
    }
    
}

总结:不管只用哪种方式,开辟内存,都要把内存释放掉。尽量在哪里使用就在哪里释放。


文章内容来源为尚学堂夏云中老师的C语言课程。


抱歉!评论已关闭.