使用json-c的json_tokener_parse解析JSON时出现段错误,求排查原因
分析你的段错误原因与修复方案
你的代码触发段错误的核心原因,以及几个关键问题我帮你梳理清楚了:
核心崩溃原因
json_tokener_parse要求传入以空字符'\0'结尾的C字符串,但你通过mmap映射的JSON文件原始内容并不自带这个终止符。当解析函数试图读取超出文件映射区域的内存时,就会访问非法地址,直接触发段错误。
除此之外,代码里还有几个会加剧或引发崩溃的问题:
- 变量名冲突:你定义了
struct stat stat;,变量名stat和系统结构体名重名,虽然C语言允许,但容易造成混淆,甚至在部分编译环境下引发异常。 - 未检查系统调用返回值:
open、fstat、mmap都可能调用失败(比如文件不存在、权限不足),如果忽略错误继续使用无效值(比如mmap返回MAP_FAILED无效指针),后续操作必然崩溃。 - 权限不匹配:你以
O_RDONLY只读打开文件,但mmap时指定了PROT_WRITE可写权限,这会导致mmap调用失败,返回无效指针。
修复后的完整代码
#include <sys/mman.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <string.h> #include <json-c/json.h> int main() { const char *path = "file.json"; int fd = open(path, O_RDONLY); // 检查文件是否打开成功 if (fd == -1) { perror("Failed to open file"); return EXIT_FAILURE; } struct stat file_stat; // 重命名变量避免与结构体名冲突 int ret = fstat(fd, &file_stat); if (ret == -1) { perror("Failed to get file stat"); close(fd); return EXIT_FAILURE; } size_t size = file_stat.st_size; // 权限匹配:只读打开文件,mmap仅用PROT_READ void *addr = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); if (addr == MAP_FAILED) { perror("Failed to mmap file"); close(fd); return EXIT_FAILURE; } // 分配内存并添加空终止符,满足json_tokener_parse的要求 char *json_str = malloc(size + 1); if (!json_str) { perror("Failed to allocate memory"); munmap(addr, size); close(fd); return EXIT_FAILURE; } memcpy(json_str, addr, size); json_str[size] = '\0'; // 手动添加字符串终止符 json_object *jobj = json_tokener_parse(json_str); if (!jobj) { fprintf(stderr, "Failed to parse JSON content\n"); free(json_str); munmap(addr, size); close(fd); return EXIT_FAILURE; } // 这里可以添加你的JSON处理逻辑,比如打印解析结果 printf("JSON parsed successfully: %s\n", json_object_to_json_string(jobj)); // 释放所有资源,避免内存泄漏 json_object_put(jobj); free(json_str); munmap(addr, size); close(fd); return EXIT_SUCCESS; }
关键修复点说明
- 添加空终止符:通过
malloc分配比文件大小多1字节的内存,复制映射内容后手动添加'\0',确保解析函数能正确识别字符串边界。 - 修正变量名:将
struct stat stat改为struct stat file_stat,避免与系统结构体名冲突。 - 完善错误检查:对所有系统调用的返回值做校验,出错时及时释放资源并退出,避免无效操作。
- 权限匹配:只读打开文件时,
mmap使用PROT_READ权限,同时改用MAP_PRIVATE(只读场景下更安全,无需共享映射)。 - 资源清理:添加了
munmap、close、free以及json_object_put(释放json-c创建的对象),彻底避免内存泄漏。
内容的提问来源于stack exchange,提问作者BODDU MANOHAR REDDY
相关产品推荐
相关产品推荐

