strtok()包装函数上的Valgrind错误

时间:2018-08-18 16:00:23

标签: c valgrind strtok

我正在尝试为strtok()创建包装器函数,但是在标记输入字符串之前,我希望该函数按如下方式处理字符串
1.如果第一个字符是,,则插入一个字符说N作为第一个字符,后跟,
2.如果两个,字符紧跟在后,则在它们之间插入一个说N的字符。
3.如果,;字符紧随其后,则在它们之间插入一个说N的字符。
尝试在strncpy()之前重新分配。

str = realloc(str, (strlen(array) + 1) * sizeof(char));

我的解决方案:

#define ARRAY_SIZE 100000

int
utils_to_array(char **ret, char *str, char *delim)
{
  char array[ARRAY_SIZE];

  for (int y = 0, z = 0; str[y] != '\0'; y++, z++){ /* LINE 43*/
    if ((str[y] == '\0') && (str[y + 1] == delim[0])){ /* ,*/
      array[z] = 'N';
      ++y;
      ++z;
      array[z] = ',';
    } else if ((str[y] == delim[0]) && (str[y + 1] == delim[0])) { /*,, */
      array[z] = str[y];
      z++;
      array[z] = 'N';
      y++;
      z++;
      array[z] = str[y];
    } else if ((str[y] == delim[0]) && (str[y + 1] == delim[1])) { /* ,; */
      array[z] = str[y];
      z++;
      array[z] = 'N';
      y++;
      z++;
      array[z] = str[y];

    } else {
      array[z] = str[y];
    }
  }

  str = strncpy(str, array, strlen(array)); /* LINE 71 */

  size_t n = 0;
  for (char *p = strtok(str, delim); p ; p = strtok(NULL, delim)) { /* LINE 74 */
    ret[n++] = p;
  }

  return 0;
}

Valgrind mem测试:

==7534== Conditional jump or move depends on uninitialised value(s)
==7534==    at 0x4C2CAA8: __strlen_sse42 (vg_replace_strmem.c:462)
==7534==    by 0x400BBA: utils_to_array (fxt_utils.c:71)
==7534==    by 0x400F4A: parser_gsection_new (fxt_parser.c:115)
==7534==    by 0x40096E: main (test_parser.c:10)
==7534== 
==7534== Use of uninitialised value of size 8
==7534==    at 0x54DAB1E: strtok (in /usr/lib64/libc-2.17.so)
==7534==    by 0x400C3D: utils_to_array (fxt_utils.c:74)
==7534==    by 0x400F4A: parser_gsection_new (fxt_parser.c:115)
==7534==    by 0x40096E: main (test_parser.c:10)
==7534== 
==7534== Use of uninitialised value of size 8
==7534==    at 0x54DAB4E: strtok (in /usr/lib64/libc-2.17.so)
==7534==    by 0x400C3D: utils_to_array (fxt_utils.c:74)
==7534==    by 0x400F4A: parser_gsection_new (fxt_parser.c:115)
==7534==    by 0x40096E: main (test_parser.c:10)
==7534== 
==7534== Conditional jump or move depends on uninitialised value(s)
==7534==    at 0x54DAB51: strtok (in /usr/lib64/libc-2.17.so)
==7534==    by 0x400C3D: utils_to_array (fxt_utils.c:74)
==7534==    by 0x400F4A: parser_gsection_new (fxt_parser.c:115)
==7534==    by 0x40096E: main (test_parser.c:10)
==7534== 
==7534== 
==7534== HEAP SUMMARY:
==7534==     in use at exit: 18,812 bytes in 7 blocks
==7534==   total heap usage: 7 allocs, 0 frees, 18,812 bytes allocated
==7534== 
==7534== LEAK SUMMARY:
==7534==    definitely lost: 208 bytes in 1 blocks
==7534==    indirectly lost: 0 bytes in 0 blocks
==7534==      possibly lost: 0 bytes in 0 blocks
==7534==    still reachable: 18,604 bytes in 6 blocks
==7534==         suppressed: 0 bytes in 0 blocks
==7534== Rerun with --leak-check=full to see details of leaked memory
==7534== 
==7534== For counts of detected and suppressed errors, rerun with: -v
==7534== Use --track-origins=yes to see where uninitialised values come from
==7534== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0)

如果我使用

if (str[0] == ',') { /* LINE 44 */

我收到以下valgrind错误

> ==11195== Conditional jump or move depends on uninitialised value(s)
> ==11195==    at 0x400B79: utils_to_array (fxt_utils.c:43)
> ==11195==    by 0x400F1D: parser_gsection_new (fxt_parser.c:115)
> ==11195==    by 0x40096E: main (test_parser.c:10)
> ==11195== 
> ==11195== Conditional jump or move depends on uninitialised value(s)
> ==11195==    at 0x4C2CAA8: __strlen_sse42 (vg_replace_strmem.c:462)
> ==11195==    by 0x400B8D: utils_to_array (fxt_utils.c:72)
> ==11195==    by 0x400F1D: parser_gsection_new (fxt_parser.c:115)
> ==11195==    by 0x40096E: main (test_parser.c:10)
> ==11195== 
> ==11195== 
> ==11195== Process terminating with default action of signal 11 (SIGSEGV)
> ==11195==  Bad permissions for mapped region at address 0x1FFEFFFD6A
> ==11195==    at 0x1FFEFFFD6A: ???
> ==11195==    by 0x1FFEFFFD7F: ???
> ==11195==    by 0x2C4E2C4E2C4DFFFF: ???
> ==11195==    by 0x2C4E2C4E2C4E2C4D: ???
> ==11195==    by 0x2C4E2C4E2C4E2C4D: ???
> ==11195==    by 0x2C4E2C4E2C4E2C4D: ???
> ==11195==    by 0x2C4E2C4E2C4E2C4D: ???
> ==11195==    by 0x2C4E2C4E2C4E2C4D: ???
> ==11195==    by 0x2C4E2C4E2C4E2C4D: ???
> ==11195==    by 0x2C4E2C4E2C4E2C4D: ???
> ==11195==    by 0x2C4E2C4E2C4E2C4D: ???
> ==11195==    by 0x2C4E2C4E2C4E2C4D: ???
> ==11195== 
> ==11195== HEAP SUMMARY:
> ==11195==     in use at exit: 18,812 bytes in 7 blocks
> ==11195==   total heap usage: 7 allocs, 0 frees, 18,812 bytes allocated
> ==11195== 
> ==11195== LEAK SUMMARY:
> ==11195==    definitely lost: 208 bytes in 1 blocks
> ==11195==    indirectly lost: 0 bytes in 0 blocks
> ==11195==      possibly lost: 0 bytes in 0 blocks
> ==11195==    still reachable: 18,604 bytes in 6 blocks
> ==11195==         suppressed: 0 bytes in 0 blocks
> ==11195== Rerun with --leak-check=full to see details of leaked memory
> ==11195== 
> ==11195== For counts of detected and suppressed errors, rerun with: -v
> ==11195== Use --track-origins=yes to see where uninitialised values come from
> ==11195== ERROR SUMMARY: 3 errors from 2 contexts (suppressed: 0 from 0)

字符串输入示例:

  

,, 126HC:\ Users \ 410239 \ Documents \ Work \ Queries \ Lapa Parts   17-08-2017 \ AA00001106762_Ao_REINFORCEMENT \ AA00001106762_AO_REINFORCEMENT.stp,30HAA00001106762_AO_REINFORCEMENT,22HAutodesk   Inventor 2016,7Hunknown,32,38,7,99,   15,,1.,2,2HMM,1,0.08,15H20180314.163749,0.01,10000。,4Hnone,4Hnone,11,0,   15H20170818.085306;

1 个答案:

答案 0 :(得分:0)

由于strsep()可以处理空字段,因此在字段为空时不再需要插入N。这就是我使用@rici发送的linux手册页和链接解决问题的方式:
https://github.com/freebsd/freebsd/blob/master/sys/libkern/strsep.c
Is there a windows variant of strsep()

int
utils_to_array(char **ret, char *str, char *delim)
{
  size_t count = 0;
  char *tok;

  while((tok = strsep(&str, delim)) && count < PARAM_MAX)
        ret[count++] = tok;

  return 0;
}