zoukankan      html  css  js  c++  java
  • 关于strsep函数以及联想

    今天在调用strsep函数时,报了Segmentation fault错误,strsep函数原型如下:

    char *strsep(char **stringp, const char *delim);

    第一个参数是个二级指针,而且没有const修饰,我猜测在man手册中只要是添加const修饰的参数都是只读的(当然这是肯定的),而那些没有添加const修饰的一般为可读可写的。

    根据这种猜测,再根据调用strsep时。传递的第一个参数是一个const char *,这时程序运行时就回报Segmentation fault错误。

    例:

     1 #include <stdio.h>
     2 
     3 int main(void)
     4 {
     5     char *buf = "123456,123456";
     6 
     7     strsep(&buf, ",");
     8 
     9     return 0;
    10 }

    编译运行结果:

    # ./a.out 
    Segmentation fault

    修改如下:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 
     5 int main(void)
     6 {
     7     char *buf = malloc(32);
     8 
     9     memcpy(buf, "123456,123456", sizeof("123456,123456"));
    10 
    11     strsep(&buf, ",");
    12 
    13     return 0;
    14 }

    另一种修改方式:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 
     5 int main(void)
     6 {
     7     char buf[32] = {0};
     8     
     9     memcpy(buf, "123456,123456", sizeof("123456,123456"));
    10 
    11     strsep(&buf, ",");
    12 
    13     return 0;
    14 }

    上边这种修改在编译的时候会有一个警告:

    4.c: In function ‘main’:
    4.c:13:5: warning: passing argument 1 of ‘strsep’ from incompatible pointer type [enabled by default]
         strsep(&buf, ",");
         ^
    In file included from 4.c:3:0:
    /usr/include/string.h:555:14: note: expected ‘char ** __restrict__’ but argument is of type ‘char (*)[32]’
     extern char *strsep (char **__restrict __stringp,
                  ^

    可以将strsep(&buf, ",");修改为strsep((char **)(&buf), ",");以消除影响。但是这个并不是导致问题的所在。

    上边的修改并没有解决问题。

    再次修改:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 
     5 int main(void)
     6 {
     7     char buf[32] = {0};
     8     char *tmp = NULL;
     9     
    10     memcpy(buf, "123456,123456", sizeof("123456,123456"));
    11 
    12     tmp = buf;
    13     strsep(&tmp, ",");
    14 
    15     return 0;
    16 }

    以上两种方式都可以解决所遇到的问题。

    这是什么原因的导致的呢!以下是从glibc中找到的源码:

     1 char *
     2 __strsep (char **stringp, const char *delim)
     3 {
     4   char *begin;
     5 
     6   assert (delim[0] != '');
     7 
     8   begin = *stringp;
     9   if (begin != NULL)
    10     {
    11       char *end = begin;
    12 
    13       while (*end != '' || (end = NULL))
    14     {
    15       const char *dp = delim;
    16 
    17       do
    18         if (*dp == *end)
    19           break;
    20       while (*++dp != '');
    21 
    22       if (*dp != '')
    23         {
    24           *end++ = '';
    25           break;
    26         }
    27 
    28       ++end;
    29     }
    30 
    31       *stringp = end;
    32     }
    33 
    34   return begin;
    35 }
     1 char *
     2 __strsep (char **stringp, const char *delim)
     3 {
     4   char *begin, *end;
     5 
     6   begin = *stringp;
     7   if (begin == NULL)
     8     return NULL;
     9 
    10   /* Find the end of the token.  */
    11   end = begin + strcspn (begin, delim);
    12 
    13   if (*end)
    14     {
    15       /* Terminate the token and set *STRINGP past NUL character.  */
    16       *end++ = '';
    17       *stringp = end;
    18     }
    19   else
    20     /* No more delimiters; this is the last token.  */
    21     *stringp = NULL;
    22 
    23   return begin;
    24 }

    以上是在glic中找到的俩种实现方法,这两种方式都对stringp中的数据进行了修改,所以才会出现上述错误。

    在解决问题的过程中,还遇见一个问题:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 
     5 int main(void)
     6 {
     7     char *buf = malloc(32);
     8     
     9     buf = "123456,123456";
    10 
    11     memcpy(buf, "123456,123456", sizeof("123456,123456"));
    12 
    13     strsep(&buf, ",");
    14 
    15     return 0;
    16 }

    上边这段代码在运行的时候也会报Segmentation fault错误,这其实是因为buf的指向从堆区换到了只读存储区,所以会出现错误。这个错误很容易发现,但是在编码的过程中不注意还是很容易犯的,可能是我自身的问题,以作记录,以谨记。

     

     

  • 相关阅读:
    android中fragment的获取与隐藏
    Android Toolbar教程,Android标题栏经典设计教程
    Android6.0以后,在BroadcastReceiver中启动AlertDialog导致程序停止运行的问题及解决办法
    java数据结构和算法--------第六章
    动态规划--------0和1背包问题
    动态规划------平均切分数组之和为两部分
    java数据结构和算法-----第四章
    java数据结构和算法-------第三章
    java数据结构和算法----第二章
    动态规划----Ones and Zeroes
  • 原文地址:https://www.cnblogs.com/coolYuan/p/14373174.html
Copyright © 2011-2022 走看看