c语言内存

1、[b]C中内存分为五个区[/b]
[b]栈[/b]:用来存放函数的形参和函数内的局部变量。由编译器分配空间,在函数执行完后由编译器自动释放。
[b]堆[/b]:用来存放由动态分配函数(如malloc)分配的空间。是由程序员自己手动分配的,并且必须由程序员使用free释放。如果忘记用free释放,会导致所分配的空间一直占着不放,导致内存泄露。
[b]全局局[/b]:用来存放全局变量和静态变量。存在于程序的整个运行期间,是由编译器分配和释放的。
[b]文字常量区[/b]:例如char *c = “123456”;则”123456”为文字常量,存放于文字常量区。也由编译器控制分配和释放。
[b]程序代码区[/b]:用来存放程序的二进制代码。
例子(1)


#include <stdlib.h>
#include <stdio.h>
void main()
{
int b; //栈
char s[] = abc; //s在栈,abc在文字常量区
char *p1,*p2; //栈
char *p3 = 123456; //123456在常量区,p3在栈上
static int c =0; //全局区
p1 = (char *)malloc(10); //p1在栈,分配的10字节在堆
p2 = (char *)malloc(20); //p2在栈,分配的20字节在堆
strcpy(p1, 123456); //123456放在常量区
}

例子(2)

#include <stdlib.h>
#include <stdio.h>
char *f()
{
//s数组存放于栈上
//char s[4] = {'1','2','3','0'};
char s[4] = "abcd";
return s; //返回s数组的地址,但程序运行完s数组就被释放了
}
void main()
{
char *s;
s = f();
printf("%s", s); //打印出来乱码。因为s所指向地址已经没有数据
}
~

例子(3)

#include <stdlib.h>
#include <stdio.h>
char *f()
{
char* s = "abcd";
return s; // abc 返回的是常量区
}
int main()
{
char *s;
s = f();
printf("%s", s); //abc
}

指针和数组这里的区别★★★★★★★
2、[b]动态分配释放内存[/b]
用malloc动态分配内存后一定要判断一下分配是否成功,判断指针的值是否为NULL。
内存分配成功后要对内存单元进行初始化。
内存分配成功且初始化后使用时别越界了。
内存使用完后要用free(p)释放,注意,释放后,p的值是不会变的,仍然是一个地址值,仍然指向那块内存区,只是这块内存区的值变成垃圾了。为了防止后面继续使用这块内存,应在free(p)后,立即p=NULL,这样后面如果要使用,判断p是否为NULL时就会判断出来。
例子1


#include <stdlib.h>
#include <stdio.h>
void GetMemory(char *p)
{
p = (char *)malloc(100);
}
int main(void)
{
char *str = NULL;
GetMemory(str);
strcpy(str,"hello world");
printf(str);
}


程序首先申请一个char类型的指针str,并把str指向NULL(即str里存的是NULL的地址,*str为NULL中的值为0),调用函数的过程中做了如下动作:1申请一个char 类型的指针p,2把str的内容copy到了p里(这是参数传递过程中系统所做的),3为p指针申请了100个空间,4返回Test函数.最后程序把字符串hello world拷贝到str指向的内存空间里.到这里错误出现了!str的空间始终为NULL而并没有实际的空间.深刻理解函数调用的第2步,将不难发现问题所在!

#include <stdlib.h>
#include <stdio.h>
char *GetMemory(void)
{
char p[] = "hello world";
return p;
}
int main(void)
{
char *str = NULL;
str = GetMemory();
printf(str);
}

程序首先申请一个char类型的指针str,并把str指向NULL.调用函数的过程中做了如下动作:1申请一数组p[]并将其赋值为hello world(数组的空间大小为12),2返回数组名p付给str指针(即返回了数组的首地址).那么这样就可以打印出字符串"hello world"了么?当然是不能的!因为在函数调用的时候漏掉了最后一步.也就是在第2步return数组名后,函数调用还要进行一步操作,也就是释放内存空间.当一个函数被调用结束后它会释放掉它里面所有的变量所占用的空间.所以数组空间被释放掉了,也就是说str所指向的内容将不确定是什么东西

#include <stdlib.h>
#include <stdio.h>
void GetMemory2(char **p, int num)
{
*p = (char *)malloc(num);
}
int main(void)
{
char *str = NULL;
GetMemory2(&str,100);
strcpy(str,"hello");
printf(str);
}

正确答案为可以打印出hello.但内存泄漏了!

#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *str = (char *)malloc(100);
strcpy(str,"hello");
free(str);
if(str != NULL)
{
strcpy(str,"world");
printf(str);
}
}

申请空间,拷贝字符串,释放空间.前三步操作都没有任何问题.到if语句里的判断条件开始出错了,因为一个指针被释放之后其内容并不是NULL,而是一个不确定的值.所以if语句永远都不能被执行.这也是著名的"野"指针问题.所以我们在编写程序释放一个指针之后一定要人为的将指针付成NULL.这样就会避免出现"野"指针的出现.有人说"野"指针很可怕,会带来意想不到的错误.


参考http://blog.csdn.net/pfgmylove/article/details/3212163
有修正
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值