注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Bioinformatics home

 
 
 

日志

 
 

c里面内存分两种:栈和堆(PERL 群,主讲xu)  

2008-11-05 17:27:36|  分类: 默认分类 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

c里面内存分两种:栈和堆

我们通常的变量申明,都会导致栈上内存分配。

比如int n; 会分配一块int大小的内存给变量n

如果在32位的机器操作系统上,这块内存应该是4个字节大小。

我们知道c语言里有代码块,比如函数,if,while,for等。

代码块会产生新的局部作用域。

每新产生一个局部作用域,栈里就会多一层,这个块里申明的变量,也就在这层栈上分配内存。

当块结束的时候,这层内存栈会被回收。

所以栈上分配的内存,我们不用自己回收。(操作系统 负责实时回收)

下面看例子。

double d; long l;都会在栈上分配相应大小的内存。

下面看一个有点混淆的例子

char *p;

这个会发生什么呢?

char *p同样导致栈上内存的分配,这时分配的是一块32位,既4字节的空间,准备用于存储一个地址。

下面: p = malloc(20);

这是发生的是: 在堆上分配一块20字节的空间,并将其起始地址存到变量p的栈内存里。

malloc是一个函数,用于分配堆内存。

相似的还有calloc、alloc等,他们的区别后面再讲。

他的参数就是要分配的内存的大小。

一般我们会进行一些字符串操作,比如: strcpy(p, "hello, world");

变量申明就是分配栈内存。

栈是系统自动分配得,堆是用户申请出来得,对吗?  对

而且堆的内存要显式释放。

new是c++用的,也是堆上分配。

总结一下,变量声明一定会发生栈内存的分配。


strcpy(p, "hello, world"); 把"hello, world\0"这几个字节写到p指向的内存上,不一定是堆内存。

看下面的例子:

char str[20];


直接在栈上产生了一块20个字节大小的内存。

这个是不需自己回收的。

对他,也可以使用strcpy

strcpy(str, "hello, world");

我们可以这样: p = str;

这样,p就指向了str的那块栈内存。


这样原来给p分配的那块堆内存,就无主了。

这就是一种内存泄漏。


看到内存不断增长。

堆上分配的内存,需要使用free函数来释放。

假设p还是指向的堆内存,那么free(p);释放了这块内存。

变量p的栈内存里存放的是他指向的堆空间的地址。

如果p=str就是他指向的栈空间的地址。

释放内存以后就不应该再引用他。最好养成好习惯:

free(p); p = NULL;

那这时候应该可以这样用,比如 int p   恩,可以这样,但是会把自己搞的很混乱。

释放内存并不一定会清除那片内存的数据。只是表明其他变量现在可以重用这块内存。

其实程序只在乎变量的大小,不在乎变量的类型,类型是方便人类使用的。

int p;或者char *p;只是申明一个整数或者指针。

这个指针指向什么,还没有说明。

这一点你必须搞清楚。

整数和指针可以互转。

因为他们都是32位的。


实际上你可以这样写: int i; char *p = &i;顶多就是一个警告。

规范的写法是: int i; int *p = &i;

为了加深理解,下面再复习一下例子吧。

char * p = malloc(20); 消耗24字节内存,其中4字节栈,20字节堆。


char str[20];char *p = str; 消耗24字节,全是栈内存


int i; int *p = &i; 消耗8字节,全是栈内存。

char *p; 只消耗4字节栈内存。

好了,继续讲释放。

前面说了,释放之后,不一定会重置内存。就好象format以后,数据还是可以恢复一样。

但是,释放以后,就有可能malloc给其他指针,他的数据可能被其他指针修改。所以你最好就是不要再使

用这块内存了。

free(p); char *p2 = malloc(20); printf("%s\n", p);

这里malloc会随机分配内存给p2,如果你rp超好,刚好是分配到p原来的那块。

然后在打印之前,strcpy(p2, "fuck world");

内存被修改了,打出来的结果就变了。

不过这种几率很小。

不过还是要避免。

free了以后,就绝对不要再使用了。

free以后,一定要p = NULL;

我们前面说malloc函数有很多种个。具体的差别就是,有的函数分配了内存以后,会把内存的每个字节都

设成\0。

不过,就好的习惯来说,拿到一块内存以后,应该先对其进行初始化,然后才使用。

p = malloc(20); strcpy(p, "hello"); printf("%s\n", p);

如果你直接写: p = malloc(20); printf("%s\n", p);  这样没什么道理

%s的话会打内存地址指向的空间的内容。
规范来说,都是先strcpy以后才printf

打印自己想打的东西。
类似的道理

问题主要容易出在结构指针上

struct people { int age; };

struct people *p = malloc(sizeof(struct people));

printf("%d\n", p->age);
在有些编译器下,这样打出来的不一定是0
可能会是脏内存的数据。
所以分配内存以后应该先做初始化: p->age = 0;

好了,总结一下:分配内存以后,一定对数据赋值以后,才使用,释放内存以后,一定把指针指像NULL,并且不再使用他。

  评论这张
 
阅读(741)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017