有如下一段代码,意图把“zhongxiaoming"字符串赋值进以p为首地址的空间为15字节的内存空间,然后释放p所指向的内存,以免出现内存泄露。
该代码出现几个问题,涉及到内存的赋值、malloc函数以及free函数的用法,以及字符串的相关知识。
1 #include <stdio.h>
2 #include <stdlib.h>3
4 int main()
5 {
6 char *p = (char*)malloc(15);
7 int i=0;
8 p="zhongxiaoming";
9 for(;i<15;i++)
10 {
11 printf("p[%d]:%c\t",i,*(p+i));
12 }
13 printf("\n");
14 free(p);
15 p=NULL;
16 printf("ok\n");
17 return 0;
18 }
===================================================================
编译运行后:
Love-Yan:pointertest MD101$ make
 gcc -o malloctest malloctest.c -g
 Love-Yan:pointertest MD101$ ./malloctest
 p[0]:z p[1]:h  p[2]:o p[3]:n  p[4]:g p[5]:x  p[6]:i p[7]:a  p[8]:o p[9]:m  p[10]:i p[11]:np[12]:g p[13]:p[14]:p 
 malloctest(3232) malloc: *** error for object 0x107a45f4e: pointer being freed was not allocated
 *** set a breakpoint in malloc_error_break to debug
 Abort trap: 6
可知道,pointer being freed was not allocated。意思是,意图释放的指针(p)没有被分配,这是什么意思呢?明明malloc了15字节的空间,怎么说没有被分配呢?
原来:
malloc========================================
8 p="zhongxiaoming"; 这行语句打乱了所有的计划,导致分配出来的15字节空间丢失了,内存泄露掉了。
6 char *p = (char*)malloc(15);这时候的p才是15字节的真正主人。
按照本意,我们采用strcpy就可以把“zhongxiaoming”拷贝进p指向的内存。不过,要记得加进<string.h>头文件哦。具体代码:
strcpy(p,"zhongxiaoming");这样,p对应的连续15个内存地址就依次被赋值了,当然,只是赋值了strlen(“zhongxiaoming”)+1个字节,后面的应该保持不变,因为malloc分配出来的空间不会对内存进行初始化,而new操作符分配出来的会初始化。
字符串、内存静态区======================================
第八行代码把在静态区创建的字符串常量“zhongxiaoming”的首地址赋值给了p,此时,指针变量p的值发生了变化,不再是指向15个字节的首地址了。
此时,可以通过p对字符串常量进行读的操作(无写操作,字符常量不允许修改,通常在静态区的内容,很多都是字符常量、整形常量等等,譬如int a=12;doule b=123.123123;
这里的12和123.123123都是放在静态区的,他们都有个地址,这些常量与a、b对应,读a也就是读a对应的12.可是如果再有对a 的重新赋值,则常量区的12将会在某个时刻被系统回收掉,可以肯定的是,程序结束后肯定被释放掉了,呵呵。。。重新赋值a,如a=12312,则又在静态区创建12312与a对应,以此类推。),在此特别引申一点:
指针对应的字符串的访问还可以通过poiner[i]操作符进行访问。当然,在这里是想把“zhongxiaoming”全部读出来。而p又指向其对应的地址(其实,用&(“zhongxiaoming”)可得到其地址),故我们可以通过p[i]进行访问,当然了,不能写哦,常量嘛,静态区嘛。。。那我们就这样完成了对常量区字符串“zhongxiaoming”的读操作啦。当然,这是没有修改过的源代码的功能。
free===================================================
按照没有修改过的源代码,直接就free(p),也太夸张了吧,把p(也就是&(“zhongxiaoming”)对应的内存释放),这是要逆天了?想去释放静态区的内存。。嘿嘿,这可是系统自己的事,最好还是别干预了。所以,系统报错。。。说,malloctest(2617) malloc: *** error for object 0x107b27f48: pointer being freed was not allocated。也就是说,这不是你分配的内存,这段内存不归你管。。。
修改代码==================================================
而加入strcpy的新代码,要对p对应的内容进行访问也就是有【】操作符或者*(p+i)了,千万别写成&p+i哦,这样子可是会挎了15个字节访问了哦。。。我们把代码修改下:
#include <stdio.h>
   2 #include <stdlib.h>
   3 #include <string.h>
   4 int main()
   5 {
   6         char *p = (char*)malloc(15);
   7         int i=0;
   8         memset(p,'A',15);
   9         for(;i<15;i++)
  10         {              
  11                  printf("p[%d]:%c\t",i,p[i]);
  12         }
  13         printf("\n\n");
  14         
  15         strcpy(p,"zhongxiaoming");
  16         for(i=0;i<15;i++)
  17         {       
  18                 printf("p[%d]:%c\t",i,p[i]);
  19         }
  20         printf("\n");
  21         free(p);
  22         p=NULL;
  23         return 0;
  24 }
运行:
Love-Yan:pointertest MD101$ make
 gcc -o malloctest malloctest.c -g
 Love-Yan:pointertest MD101$ ./malloctest
 p[0]:z p[1]:h  p[2]:o p[3]:n  p[4]:g p[5]:x  p[6]:i p[7]:a  p[8]:o p[9]:m  p[10]:i p[11]:n p[12]:g p[13]: p[14]: 
 Love-Yan:pointertest MD101$ 
大功告成。。。
不过,在这里,如果要考究下strcpy对p的15个字节处理了多少个呢?我们可以先用memset来对这15个字节进行下初始化,然后再输出看看就知道了。
Love-Yan:pointertest MD101$ make
 gcc -o malloctest malloctest.c -g
 Love-Yan:pointertest MD101$ ./malloctest
 p[0]:A p[1]:A  p[2]:A p[3]:A  p[4]:A p[5]:A  p[6]:A p[7]:A  p[8]:A p[9]:A  p[10]:A p[11]:Ap[12]:A p[13]:Ap[14]:A 
 p[0]:z p[1]:h  p[2]:o p[3]:n  p[4]:g p[5]:x  p[6]:i p[7]:a  p[8]:o p[9]:m  p[10]:i p[11]:np[12]:g p[13]:p[14]:A 
 Love-Yan:pointertest MD101$ 
good news。。。只是对前面的部分字节进行了赋值。可是第十四了也就是p[13]里边的内容是空的。。这是怎么回事?
我们知道字符串的结尾是'\0‘对吧,里边会不会就是'\0'呢?我们可以gdb一下。看看这个p[13]是什么。
果然。。。
(gdb) p p[13]
 $2 = 0 '\0'
 (gdb)