我有这个函数split_text,它接受char数组text,并try 使用token作为拆分值将其拆分为子数组,res是指向每个子字符串的指针数组

int split_text(char * text, char * token, char ** res)
{
    int x =0;
    char * tmp = strtok(text , token);
    while (tmp != NULL)
    {
        res[x] = malloc(1024);
        strcpy(res[x], tmp);
        x++;
        *res = realloc(*res, sizeof(char*)*(x+1));
        tmp = strtok(NULL , token);
    }
    return x;
}

int main()
{
    char text[] = "Hello world this is elliot";

    char ** ptr = (char**)malloc(sizeof(char*));

    int x = split_text(text, " ", ptr);

    
    for (int i =0; i< x; i++)
        printf("%s\n", ptr[i]);
    
    return 0;
}

当编译这段代码时,它工作得很好,因为它在新的一行上显示每个子字符串,但当运行valgrind时,我得到了许多Invalid write of size 8Invalid read of size 8

以下是完整的valgrind个输出

==74210== Memcheck, a memory error detector
==74210== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==74210== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==74210== Command: ./a.out
==74210== 
==74210== Invalid write of size 8
==74210==    at 0x1091D0: split_text (split.c:23)
==74210==    by 0x1092B2: main (split.c:38)
==74210==  Address 0x4a3f048 is 0 bytes after a block of size 8 alloc'd
==74210==    at 0x483F7B5: malloc (vg_replace_malloc.c:381)
==74210==    by 0x109294: main (split.c:36)
==74210== 
==74210== Invalid read of size 8
==74210==    at 0x1091E7: split_text (split.c:24)
==74210==    by 0x1092B2: main (split.c:38)
==74210==  Address 0x4a3f048 is 0 bytes after a block of size 8 alloc'd
==74210==    at 0x483F7B5: malloc (vg_replace_malloc.c:381)
==74210==    by 0x109294: main (split.c:36)
==74210== 
Hello
==74210== Invalid read of size 8
==74210==    at 0x1092D3: main (split.c:42)
==74210==  Address 0x4a3f048 is 0 bytes after a block of size 8 alloc'd
==74210==    at 0x483F7B5: malloc (vg_replace_malloc.c:381)
==74210==    by 0x109294: main (split.c:36)
==74210== 
world
this
is
elliot
==74210== 
==74210== HEAP SUMMARY:
==74210==     in use at exit: 4,152 bytes in 6 blocks
==74210==   total heap usage: 12 allocs, 6 frees, 6,312 bytes allocated
==74210== 
==74210== LEAK SUMMARY:
==74210==    definitely lost: 4,104 bytes in 5 blocks
==74210==    indirectly lost: 48 bytes in 1 blocks
==74210==      possibly lost: 0 bytes in 0 blocks
==74210==    still reachable: 0 bytes in 0 blocks
==74210==         suppressed: 0 bytes in 0 blocks
==74210== Rerun with --leak-check=full to see details of leaked memory
==74210== 
==74210== ERROR SUMMARY: 12 errors from 3 contexts (suppressed: 0 from 0)
==74210== 
==74210== 4 errors in context 1 of 3:
==74210== Invalid read of size 8
==74210==    at 0x1092D3: main (split.c:42)
==74210==  Address 0x4a3f048 is 0 bytes after a block of size 8 alloc'd
==74210==    at 0x483F7B5: malloc (vg_replace_malloc.c:381)
==74210==    by 0x109294: main (split.c:36)
==74210== 
==74210== 
==74210== 4 errors in context 2 of 3:
==74210== Invalid read of size 8
==74210==    at 0x1091E7: split_text (split.c:24)
==74210==    by 0x1092B2: main (split.c:38)
==74210==  Address 0x4a3f048 is 0 bytes after a block of size 8 alloc'd
==74210==    at 0x483F7B5: malloc (vg_replace_malloc.c:381)
==74210==    by 0x109294: main (split.c:36)
==74210== 
==74210== 
==74210== 4 errors in context 3 of 3:
==74210== Invalid write of size 8
==74210==    at 0x1091D0: split_text (split.c:23)
==74210==    by 0x1092B2: main (split.c:38)
==74210==  Address 0x4a3f048 is 0 bytes after a block of size 8 alloc'd
==74210==    at 0x483F7B5: malloc (vg_replace_malloc.c:381)
==74210==    by 0x109294: main (split.c:36)
==74210== 
==74210== ERROR SUMMARY: 12 errors from 3 contexts (suppressed: 0 from 0)

我知道它正在从无效的内存位置读取和写入,但它仍然将拆分的文本作为子字符串输出

为什么会出现这些错误,以及如何修复它们?

推荐答案

至少这句话

*res = realloc(*res, sizeof(char*)*(x+1))

这相当于

res[0] = realloc(res[0], sizeof(char*)*(x+1))

这说不通.

它总是重新分配指针res所指向的指针数组的第一个元素.

结果,指针res所指向的数组在Main中只分配了一个元素.

所以这个调用strcpy

strcpy(res[x], tmp);

至少在x不等于0时调用未定义的行为.

请注意,如果您想要更改函数split_text内Main中声明的指针ptr,则需要通过引用将其传递给函数.也就是说,函数的第三个参数应该声明如下

int split_text(char * text, char * token, char *** res);

对于函数定义,您需要 for each 新元素分配一个指针的内存,还需要分配一个由指针指向的字符数组,其中将复制子字符串.

C++相关问答推荐

GCC:try 使用—WError或—pedantic using pragmas

将整数的.csv文件解析为C语言中的二维数组

为什么C语言允许你使用var =(struct NAME){

为什么我一直收到分段错误?

C lang:当我try 将3个或更多元素写入数组时,出现总线错误

字符是否必须转换为无符号字符,然后才能与getc家族的返回值进行比较?

VS代码';S C/C++扩展称C23真关键字和假关键字未定义

C中的FREE函数正在触发断点

将字符串数组传递给C中的函数:`str[dim1][str_size]`vs`*str[dim1]`

将数组插入数组

将多项式从文件.txt加载到终端时出现问题

Matlab/Octave对conv2函数使用哪种方法?

在我的函数中实现va_arg的问题

在C中使用字符串时是否不需要内存分配?

我错误地修复了一个错误,想了解原因

从系统派生线程调用CRT

程序打印一些随机空行

使用 strtok 多次分割一个字符串会导致意外行为

如何使用 VLA 语法使用 const 指针声明函数

文件指针引起的C程序分段错误