有如下一段代码,意图把“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 ",i,*(p+i));
12 }
13 printf(" ");
14 free(p);
15 p=NULL;
16 printf("ok ");
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 ",i,p[i]);
12 }
13 printf("
");
14
15 strcpy(p,"zhongxiaoming");
16 for(i=0;i<15;i++)
17 {
18 printf("p[%d]:%c ",i,p[i]);
19 }
20 printf("
");
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]里边的内容是空的。。这是怎么回事?
我们知道字符串的结尾是' ‘对吧,里边会不会就是' '呢?我们可以gdb一下。看看这个p[13]是什么。
果然。。。
(gdb) p p[13]
$2 = 0 ' '
(gdb)