内存管理-Linux下C编程指南

1.

静态内存

编译的时候预申请的内存,不需要自己管理,所属函数执行完毕后自动回收

缺陷:

类似下面的函数会出错:

char *uppr(char *oldstring)
{
    char newstring[100];
    ...
    return newstring;
}

因为函数执行完毕后字符数组new已经被销毁了,指针指向的位置当然就不是正确的地址。

此函数可以通过以下方式解决:

void uppr(char *old,char *new)
{
    ...
}

可以将两个字符数组传入,然后将更改写回new中。

可以实现的原因是new 所代表的数组地址是主函数定义的,更改不会随着子函数销毁而销毁,因此在子函数中对主函数变量指针的改变可以实现,经典实现就是双返回的交换

如下:

void swap(int *a,int *b)
{
    int c;
    c=*a;
    *a=*b;
    *b=c;
}

调用
swap(&a,&b);

2.

溢出

使用了超出已申请的内存,就是在申请数组是100个元素的情况下写入了101及以上个元素,或企图读取到101个及以上位置的元素

引用错误的结果不可预期,通常安全性都出自溢出区,读取了本来不能读取的位置而启动了另外的程序。

写入的错误可能会导致其他程序的数据被覆盖,程序也会出现错误。

解决方式:

通常是在进行操作时判断空间大小,进行截取,即将超出部分删除,但是这样会导致数据丢失

3.

动态内存

在程序运行过程中动态进行分配的内存,通常是自己申请

主要函数

#include<stdlib.h>
void *malloc(size_t size)
void *calloc(size_t nmemb,size_t size)
释放内存
void *free(void *ptr)
调整内存
void *realloc(void *ptr,size_t size)

 

注意动态内存的释放不由系统决定,而是必须使用free函数才能释放,因此在子函数中可以返回指向申请的内存的指针

例如:

char *uppr(char *old)
{
    char *new;
    if(new=malloc(strlen(old)+1)){
        strcpy(new,old);
        int i;
        for(i=0;i<strlen(new);++i){
            if(new[i]>=97 && new[i]<=122){
                new[i]-=32;
            }
        }
    }else{
        exit(255);
    }
    return new;
}

此时子函数执行完毕后new并不会被销毁,因此可以返回此地址,但是在使用完毕后最好将他是free掉。

另外,realloc函数当ptr为NULL时,等价于malloc,size为0时,相当于free

注意free后指针变为悬空指针,不可以访问(不是不能,访问悬空指针会发生不可预知的异常)。

4.

分配堆栈

#include<stdlib.h>
void *alloca(size_t size)

此时分配的内存在函数结束时被自动收回,一般很少用

5.

内存锁定

一般情况下,如果内存一段时间内不使用,系统会自动将其转移到磁盘上原位置放置新数据,如果想禁止此区域被转移,可以使用内存锁定

常用函数为

#include<sys/types.h>
//锁定内存首地址+长度 int mlock(const void *addr,size_t length);
//解锁内存,首地址+长度
int munlock(void *addr,size_t lemgth);
/*锁定内存页,flag选项:
*MCL_CURRENT  所有内存页
*MCL_FUTURE  所有为进程添加的地址页
*/
int mlockall(int flag); int munlockall(void);

(以上函数只限root用户)

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。