尝试手动将 char32_t 字符串拆分为标记时出现无效的未初始化跳转或移动内存错误

问题描述 投票:0回答:1

我正在尝试将

char32_t
字符串拆分为由分隔符分隔的标记。我没有使用任何 strtok 或其他 std 库函数,因为输入字符串和定界符将是多字节 unicode 字符串。

这是我写的函数:

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <uchar.h>
#include <wchar.h>

char32_t **sp(char32_t *str, char32_t delim, int *len) {
  *len = 1;
  char32_t *s = str;
  while (*s != U'\0') {
    if (*s == delim) {
      (*len)++;
    }
    s++;
  }
  char32_t **tokens = (char32_t **)malloc((*len) * sizeof(char32_t *));
  if (tokens == NULL) {
    exit(111);
  }

  char32_t * p = str;
  int i = 0;
  while (*p != U'\0') {
    int tok_len = 0;
    while (p[tok_len] != U'\0' && p[tok_len] != delim) {
      tok_len++;
    }
    tokens[i] = (char32_t *)malloc(sizeof(char32_t) * (tok_len + 1));
    if (tokens[i] == NULL) {
      exit(112);
    }
    memcpy(tokens[i], p, tok_len * sizeof(char32_t));
    tokens[i][tok_len] = U'\0';
    p += tok_len + 1;
    i++;
  }
  return tokens;
}

这是驱动程序代码

int main() {
  char32_t *str = U"Hello,World,mango,hey,";
  char32_t delim = U',';
  int len = 0;
  char32_t ** tokens = sp(str, delim, &len);
  wprintf(L"len -> %d\n", len);
  for (int i = 0; i < len; i++) {
    if (tokens[i]) {
    
    wprintf(L"[%d] %ls\n" , i , tokens[i]);  
    }
    free(tokens[i]);
  }  
  free(tokens);

}

这里是输出:

len -> 5
[0] Hello
[1] World
[2] mango
[3] hey
[4] (null)

但是当我用 valgrind 检查程序时,它显示多个内存错误

valgrind -s --leak-check=full --track-origins=yes ./x3
==7703== Memcheck, a memory error detector
==7703== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==7703== Using Valgrind-3.20.0 and LibVEX; rerun with -h for copyright info
==7703== Command: ./x3
==7703== 
tok -> 5
tok -> 5
tok -> 5
tok -> 3
len -> 5
[0] Hello
[1] World
[2] mango
[3] hey
==7703== Conditional jump or move depends on uninitialised value(s)
==7703==    at 0x48FDAF8: __wprintf_buffer (vfprintf-process-arg.c:396)
==7703==    by 0x48FF421: __vfwprintf_internal (vfprintf-internal.c:1459)
==7703==    by 0x490CFAE: wprintf (wprintf.c:32)
==7703==    by 0x1093C9: main (main.c:51)
==7703==  Uninitialised value was created by a heap allocation
==7703==    at 0x4841888: malloc (vg_replace_malloc.c:393)
==7703==    by 0x1091FC: sp (main.c:17)
==7703==    by 0x109384: main (main.c:47)
==7703== 
[4] (null)
==7703== Conditional jump or move depends on uninitialised value(s)
==7703==    at 0x4844225: free (vg_replace_malloc.c:884)
==7703==    by 0x1093DA: main (main.c:52)
==7703==  Uninitialised value was created by a heap allocation
==7703==    at 0x4841888: malloc (vg_replace_malloc.c:393)
==7703==    by 0x1091FC: sp (main.c:17)
==7703==    by 0x109384: main (main.c:47)
==7703== 
==7703== 
==7703== HEAP SUMMARY:
==7703==     in use at exit: 0 bytes in 0 blocks
==7703==   total heap usage: 7 allocs, 7 frees, 5,248 bytes allocated
==7703== 
==7703== All heap blocks were freed -- no leaks are possible
==7703== 
==7703== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
==7703== 
==7703== 1 errors in context 1 of 2:
==7703== Conditional jump or move depends on uninitialised value(s)
==7703==    at 0x4844225: free (vg_replace_malloc.c:884)
==7703==    by 0x1093DA: main (main.c:52)
==7703==  Uninitialised value was created by a heap allocation
==7703==    at 0x4841888: malloc (vg_replace_malloc.c:393)
==7703==    by 0x1091FC: sp (main.c:17)
==7703==    by 0x109384: main (main.c:47)
==7703== 
==7703== 
==7703== 1 errors in context 2 of 2:
==7703== Conditional jump or move depends on uninitialised value(s)
==7703==    at 0x48FDAF8: __wprintf_buffer (vfprintf-process-arg.c:396)
==7703==    by 0x48FF421: __vfwprintf_internal (vfprintf-internal.c:1459)
==7703==    by 0x490CFAE: wprintf (wprintf.c:32)
==7703==    by 0x1093C9: main (main.c:51)
==7703==  Uninitialised value was created by a heap allocation
==7703==    at 0x4841888: malloc (vg_replace_malloc.c:393)
==7703==    by 0x1091FC: sp (main.c:17)
==7703==    by 0x109384: main (main.c:47)
==7703== 
==7703== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

我无法弄清楚问题是什么。任何帮助将不胜感激

我也尝试过使用 unicode 字符串,同样的错误也会发生。

c string unicode valgrind char32-t
1个回答
1
投票

valgrind
给出这些错误是因为您的程序在
for
函数
 中的这个 
main() 循环的最后一次迭代中访问未初始化的内存(即在访问
tokens[4]
时,当
len
值为
5

  for (int i = 0; i < len; i++) {
     if (tokens[i]) {
        wprintf(L"[%d] %ls\n" , i , tokens[i]);  
     }
     free(tokens[i]);
  }  

要解决这个问题,在

sp()
函数中,在为
tokens
分配内存后,要么这样做:

tokens [*len - 1]= NULL;

或使用

calloc
分配内存给
tokens

char32_t **tokens = calloc((*len), sizeof(char32_t *));

使用上述任何一种解决方案,

valgrind
输出:

# valgrind -s --leak-check=full --track-origins=yes ./a.out 
==9761== Memcheck, a memory error detector
==9761== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==9761== Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info
==9761== Command: ./a.out
==9761== 
len -> 5
[0] Hello
[1] World
[2] mango
[3] hey
==9761== 
==9761== HEAP SUMMARY:
==9761==     in use at exit: 0 bytes in 0 blocks
==9761==   total heap usage: 7 allocs, 7 frees, 5,248 bytes allocated
==9761== 
==9761== All heap blocks were freed -- no leaks are possible
==9761== 
==9761== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
© www.soinside.com 2019 - 2024. All rights reserved.