You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言string_split函数初始化char指针数组遇段错误求助

解决string_split函数的段错误问题及正确实现

错误原因分析

  • 参数传递错误:string_split函数中tokens是按值传递的,函数内部malloc分配的地址无法传递回main函数,导致main里的tokens始终是NULL,打印时访问空指针触发段错误。
  • Token数量计算错误:character_count返回的是分隔符的数量,但实际Token数量应该是分隔符数量+1(比如字符串"a\nb\nc"有2个\n,对应3个Token),当前代码malloc的数组大小不足,会导致数组越界访问。
  • strtok参数不规范:strtok的第二个参数要求是字符串(char*指向的以\0结尾的字符序列),虽然传入&del在单个分隔符场景下能工作,但更规范的写法是直接使用字符串字面量或构造合法字符串。

修正后的完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

char** string_split(char *buffer, char del, uint32_t *out_len);
uint32_t character_count(char *str, char c);

int main(int argc, char *argv[]) 
{
    uint32_t i, len;
    char *buffer = NULL;
    long length;
    FILE *f;
    char **tokens = NULL;
        
    if (argc < 2)
    {
        printf("usage: %s <config_file>\n", argv[0]);
        return 0;
    }

    f = fopen(argv[1], "rb");
    if (f)
    {
        fseek(f, 0, SEEK_END);
        length = ftell(f);
        fseek(f, 0, SEEK_SET);
        buffer = malloc(length + 1);
        if (buffer)
        {
            fread(buffer, 1, length, f);
            buffer[length] = '\0';
        }
        fclose(f);
    }

    if (buffer)
    {
        tokens = string_split(buffer, '\n', &len);
        printf("len:%d\n", len);

        for(i = 0; i < len; i++)
        {
            printf("%s\n", tokens[i]);
        }

        // 释放资源,避免内存泄漏
        free(tokens);
        free(buffer);
    }
    return 0;
}

char** string_split(char *buffer, char del, uint32_t *out_len)
{
    uint32_t size, cnt;
    char *token = NULL;
    char del_str[2] = {del, '\0'}; // 构造合法的分隔符字符串

    cnt = 0;
    size = character_count(buffer, del) + 1; // 修正Token数量计算
    char **tokens = malloc(size * sizeof(char *));
    if (!tokens) {
        *out_len = 0;
        return NULL;
    }
    
    token = strtok(buffer, del_str);
    if (token != NULL) {
        tokens[cnt++] = token;
    }

    while ((token = strtok(NULL, del_str)) != NULL) {
        tokens[cnt++] = token;
    }

    *out_len = cnt;
    return tokens;
}

uint32_t character_count(char *str, char c)
{
    uint32_t cnt = 0;
    // 优化遍历方式,避免重复调用strlen
    while (*str != '\0') {
        if (*str == c) {
            cnt++;
        }
        str++;
    }
    return cnt;
}

关键修改说明

  1. 调整函数接口:将string_split改为返回char**类型的Token数组,通过指针参数out_len返回Token数量,彻底解决传值导致的地址无法传递问题。
  2. 修正Token数量计算:在分隔符计数基础上加1,确保malloc的数组能容纳所有Token,避免越界访问。
  3. 规范strtok参数:构造包含分隔符的合法字符串del_str,符合strtok的参数要求。
  4. 优化性能与内存管理:修改character_count的遍历方式,避免重复调用strlen;在main中添加资源释放逻辑,避免内存泄漏。

内容的提问来源于stack exchange,提问作者Lee Brown

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 17:45:28