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

C语言中用for循环逐字符打印字符串触发段错误问题

解析维基词典JSON dump时的段错误与字符串处理问题

我用C语言解析维基词典的JSON dump文件,转成分隔格式,程序能正常运行,但用json_object_get_string打印定义内容时,会显示不需要的括号与引号。于是我尝试通过for循环逐字符打印字符串(从第4个字符开始,到终止字符前3位停止),但执行该操作时持续触发Segmentation fault(段错误)。相关代码如下:

#include <stdio.h>
#include <json-c/json.h>
#include <string.h>
#include <stdbool.h>

int main(int argc, char **argv) {
    FILE *fp;

    struct json_object *sensestr;
    int glosseslength = 0;
    char *line;
    char *line_ii;
    char *prevword = NULL;
    int d = 0;
    int n_examples = 0;
    struct json_object *parsed_json;
    struct json_object *parsed_senses;
    struct json_object *pos;
    struct json_object *word;
    struct json_object *age;
    struct json_object *senses;
    struct json_object *sense;
    struct json_object *examples;
    struct json_object *example;

    struct json_object *glosses;
    struct json_object *tags;
    struct json_object *forg_text;
    struct json_object *eng_text;

    int list = 0;
    int wordlen;
    bool has_period = false;
    bool put_newline;

    int ma = 0;
    int mb = 0;

    char *alt;

    size_t n_friends;
    size_t len;
    size_t len_ii;

    size_t read_ii;
    size_t read;
    size_t n_glosses;
    size_t i;

    fp = fopen("kaik.json","r");

    while ((read = getline(&line, &len, fp)) != -1) {
        parsed_json = json_tokener_parse(line);
        json_object_object_get_ex(parsed_json, "senses", &senses);
        json_object_object_get_ex(parsed_json, "word", &word);
        json_object_object_get_ex(parsed_json, "pos", &pos);

        wordlen = strlen(json_object_get_string(word));

        if (prevword == NULL || strcmp(prevword, json_object_get_string(word)) != 0) {
            if (list != 0) {
                printf("\n");
            }

            printf("%i. %s\t", list, json_object_get_string(word));
        }

        list = list + 1;

        free(prevword);

        prevword = strdup(json_object_get_string(word));

        printf("[%s] ", json_object_get_string(pos));

        if (json_object_object_get_ex(parsed_json, "senses", &senses)) {
            for (int x = 0; x < json_object_array_length(senses); x++) {
                sense = json_object_array_get_idx(senses, x);

                json_object_object_get_ex(sense, "glosses", &glosses);

                if (json_object_get_string(glosses)) {
                    glosseslength = strlen(json_object_get_string(glosses));

                    for (int e = 3; e < glosseslength - 3; e++) {
                        printf("%c", json_object_get_string(glosses)[e]);        // 此循环触发段错误
                    }

                    printf("%s", json_object_get_string(glosses));   // 此语句正常工作
                }

                printf(" ");
            }
        }
    }

    fclose(fp);

    printf("\n");
}

问题原因与修复方案

1. 核心错误:对JSON类型判断错误

你看到的括号和引号,本质是因为glosses是JSON数组而非字符串。json_object_get_string对数组调用时,会返回数组的字符串序列化结果(比如["定义内容"]),这就是额外符号的来源。而直接对这个字符串做下标访问时,若遇到空数组、非数组类型的glosses,会触发空指针访问或内存越界,导致段错误。

2. 正确处理glosses数组

既然glosses是数组,应该按数组类型遍历处理:

if (glosses != NULL && json_object_get_type(glosses) == json_type_array) {
    size_t gloss_count = json_object_array_length(glosses);
    for (size_t g = 0; g < gloss_count; g++) {
        struct json_object *gloss_item = json_object_array_get_idx(glosses, g);
        if (gloss_item != NULL) {
            printf("%s ", json_object_get_string(gloss_item));
        }
    }
}

3. 段错误的额外诱因

  • 原循环硬编码了字符串起始和结束位置,若glosses的字符串表示长度不足6,glosseslength -3会变成负数,导致循环条件异常,访问越界内存。
  • 多次重复调用json_object_get_string,若中间对象被意外释放,会导致空指针访问。建议将结果存入临时变量:
    char *gloss_str = json_object_get_string(gloss_item);
    if (gloss_str != NULL) {
        printf("%s ", gloss_str);
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 02:06:01