原创 指针、内存管理

2012-9-21 21:18 1489 12 12 分类: 软件与OS 文集: C语言深度解剖

 

  1. 不能把指针变量本身传递给一个函数,实现可采用两种方法。
  1. 用return返回地址;
  2. 采用二级指针。

Eg:

void GetMemory(char *p,int num)//直接把指针传递给一个函数

{

    p = (char *) malloc(num*sizeof(char));

}

 

void main(void)

{

    char * str = NULL; 

    GetMemory(str,10);//str为局部变量,当传递给函数时,函数不能真正使用str,用的只是str的一个备份,str的值不变。

    strcpy(str,"hello");//此处str的值仍然为NULL,malloc分配的内存地址并没有赋给str。如何实现呢,执行到这发生访问冲突

    free(str);

}

采用return语句实现:

char * GetMemory(char *p,int num)

{

    p = (char *) malloc(num*sizeof(char));

    return p;

}

采用二级指针实现:

void GetMemory(char * *p,int num)

{

    *p = (char *) malloc(num*sizeof(char));//直接给str赋值了

}

 

void main(void)

{

    char * str = NULL; 

    //str = GetMemory(str,10);//str为局部变量,当传递给函数时,函数不能真正使用str,用的只是str的一个备份,str的值不变。

    GetMemory(&str,10);//直接把str的地址传过去了

    strcpy(str,"hello");//此处str的值仍然为NULL,malloc分配的内存地址并没有赋给str。如何实现呢,执行到这发生访问冲突

    free(str);

}

 

  1. 函数指针(具体跟数组指针差不多)

Eg:

char * (* fun1)(char * p1,char * p2);

fun1为指针变量,指向一个带两个指针参数,返回值为char *类型的函数。

  1. 程序编译后,函数名其实就是一个地址,fun与&fun的意义是一样的。
  2. 内存管理:

堆:由malloc系列函数或new操作符分配的内存,其生命周期由free或delete决定,在没有释放前一直存在,直到程序结束。使用灵活,空间较大,易出错。

栈:即通常所说的堆栈,保存局部变量。函数运行结束时自动销毁。效率高,空间小。

静态区:保存自动全局变量和static变量(局部、全局),在整个程序的生命周期内都存在,由编译器在编译时分配。

  1. 内存错误
  1. 定义指针变量的同时最好初始化为NULL,用完指针之后也将指针变量值设为NULL。因为free(p)只是切断那块内存与p之间的联系,使p不能使用那块内存了。但p本身保存的地址并没有改变,所以free之后,需重新把p的值变为NULL,否则就成野指针了。
  2. 函数入口检测:

不管什么时候,在使用指针之前一定要确保指针是有效的。在头文件assert.h中有宏assert来检验。assert(NULL!=p)对参数进行检验,在非参数的情况下使用if(NULL!=p)来检验,这就要求指针p在定义时被初始化为NULL。Assert宏只在Debug版本上起作用,在Release版本中被编译器完全优化掉。

assert后括号里值为假时,则程序终止运行,并提示出错,为真,则继续运行。

  1. 内存泄漏:

会产生内存泄漏的内存就是堆上的内存,也就是用malloc系列函数或new操作符分配的内存。malloc分配内存如果出错则返回NULL,用if(NULL!=p)验证。

    D.  malloc与free必须配对使用。

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
12
关闭 站长推荐上一条 /3 下一条