堆栈
栈中分配局部变量空间,是系统自动分配空间。定义一个 char a;系统会自动在栈上为其开辟空间。因为栈上的空间是自动分配自动回收的,因此栈上的数据的生存周期只是在函数的运行过程当中,运行后就释放掉,不能够再访问。java
堆区分配程序员申请的内存空间,堆上的数据只要程序员不释放空间,就一直能够访问到,不过缺点是一旦忘记释放会形成内存泄露。
程序员
静态区是分配静态变量,全局变量空间的。c#
- int a = 0; 全局初始化区
- char *p1; 全局未初始化区
- main(){
- int b;
- char s[] = "abc";
- char *p2;
- char *p3 = "123456";
- static int c =0;
- p1 = (char *)malloc(10);
GetMemory1
- void GetMemory1(char *p)
- {
- p = (char *)malloc(100);
- }
-
- void Test1(void)
- {
- char *str = NULL;
- GetMemory1(str);
- strcpy(str, "hello world");
- printf(str);
- }
结果:

分析:数组
毛病出在函数GetMemory1 中。编译器老是要为函数的每一个参数制做临时副本,指针参数p的副本是 _p,编译器使 _p = p。若是函数体内的程序修改了_p的内容,就致使参数p的内容做相应的修改。这就是指针能够用做输出参数的缘由。在本例中,_p申请了新的内存,只是把 _p所指的内存地址改变了,可是p丝毫未变。因此函数GetMemory并不能输出任何东西。事实上,每执行一次GetMemory1就会泄露一块内存,由于没有用free释放内存。Test1中调用GetMemory1时,函数参数为str的副本不是str自己。ide
GetMemory2
- void GetMemory2(char **p, int num)
- {
- *p = (char *)malloc(num);
- }
-
- void Test2(void)
- {
- char *str = NULL;
- GetMemory2(&str, 100);
- strcpy(str, "hello");
- printf(str);
- }
结果:输出hello
分析:动态分配的内存不会自动释放;函数
没有测试是否成功分配了内存,应该有if (*p == NULL) { ……} 之类的语句处理内存分配失败的其状况。测试
GetMemory3
- char * GetMemory3(void)
- {
- char p[] = "hello world";
- return p;
- }
- void Test3(void)
- {
- char *str = NULL;
- str = GetMemory3();
- printf(str);
- }
结果:输出乱码。
分析:字符数组p存在于栈空间,是局部变量,函数返回后,内存空间被释放,所以输出无效值。字符数组的值是能够修改的,例如p[0] = 't‘。
spa
GetMemory4
- char *GetMemory4(void)
- {
- char *p = "hello";
- return p;
- }
-
- void Test4(void)
- {
- char *str = NULL;
- str = GetMemory4();
- cout<< str << endl;
- }
结果:输出hello
分析:p指向的是字符串常量,字符串常量保存在只读的数据段,是全局区域,但不是像全局变量那样保存在普通数据段(静态存储区)。没法对p所指的内存的内容修改,例如p[0] = 'y;这样的修改是错误的。
GetMemory5
- char *GetMemory5(void)
- {
- return "hello";
- }
- void Test3(void)
- {
- char *str = NULL;
- str = GetMemory5();
- printf(str);
- }
结果:输出hello
分析:直接返回常量区。
GetMemory6
- void GetMemory6(void) {
- char *str = (char*)malloc(100);
- strcpy(str, "hello");
- free(str);
-
- if (str != NULL) {
- strcpy(str, "world");
- printf(str);
- }
- }
-
- void main(){
- GetMemory6();
- }
结果:可以输出world,但程序存在问题。
分析:程序出现了野指针。.net
野指针只会出如今像C和C++这种没有自动内存垃圾回收功能的高级语言中, 因此java或c#确定不会有野指针的概念. 当咱们用malloc为一个指针分配一个空间后, 用完这个指针,把它free掉,可是没有让这个指针指向NULL或某一个特定的空间。如上面程序同样,将str进行free后,只是释放了指针所指的内存,但指针并无释放掉,此时指针所指的是垃圾内存;这样的话,if语句永为真,if判断无效。delete也存在一样的问题。
指针
防止产生野指针:(1)指针变量必定要初始化为NULL,由于任何指针变量刚被建立时不会自动成为NULL指针,它的缺省值是随机的。(2)当free或delete后,将指针指向NULL。一般判断一个指针是否合法,都是使用if语句测试该指针是否为NULL。
原文:http://blog.csdn.net/u013074465/article/details/42784267