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
相关产品推荐
相关产品推荐

