zoukankan      html  css  js  c++  java
  • 关于malloc与字符指针的一些易错点

     有如下一段代码,意图把“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) 


  • 相关阅读:
    跟我一起学Go系列:gRPC 全局数据传输和超时处理
    跟我一起学Go系列:Go gRPC 安全认证方式-Token和自定义认证
    c++中的继承关系
    数值型模板参数的应用
    [源码解析] 机器学习参数服务器Paracel (3)------数据处理
    [源码解析] PyTorch 分布式(2) --- 数据加载之DataLoader
    [源码解析] PyTorch 分布式(1) --- 数据加载之DistributedSampler
    [源码解析] 机器学习参数服务器 Paracel (2)--------SSP控制协议实现
    [源码解析] 机器学习参数服务器 Paracel (1)-----总体架构
    [源码解析]机器学习参数服务器ps-lite(4) ----- 应用节点实现
  • 原文地址:https://www.cnblogs.com/iosDevZhong/p/4395242.html
Copyright © 2011-2022 走看看