C语言中CONFFILE宏使用错误致create_config函数失效问题求助
C程序配置文件路径错误分析与修复
问题现象
取消注释检查配置文件是否存在的if(!fexists(CONFFILE))语句后,程序执行失败,报错信息翻译为:
错误:json_object_to_file:打开文件/home/user/.conf.json/.conf.json失败:没有该文件或目录
注释该语句时程序可正常运行。
错误根源
问题出在CONFFILE的宏定义上:
#ifdef _WIN32 #define CONFFILE strcat(getenv("LOCALAPPDATA"), "/.conf.json") #else #define CONFFILE strcat(getenv("HOME"), "/.conf.json") #endif
- 修改只读内存:
getenv()返回的是指向环境变量的只读内存区域,直接用strcat()修改该区域会触发未定义行为。 - 重复拼接路径:每次引用
CONFFILE宏都会执行一次strcat。第一次调用fexists(CONFFILE)时,已经将/.conf.json拼接到HOME路径后;第二次在create_config里调用CONFFILE时,会再次拼接,导致路径变成/home/user/.conf.json/.conf.json,这个路径显然不存在。
修复方案
1. 替换宏定义为路径生成函数
创建一个函数来生成配置文件路径,使用独立缓冲区存储,避免修改只读内存和重复拼接:
#include <stdio.h> #include <stdlib.h> #include <string.h> // 生成配置文件路径的函数 char *get_conf_file_path() { static char conf_path[256]; // 静态缓冲区,保证多次调用返回同一结果 if (conf_path[0] != '\0') { return conf_path; // 已生成过路径,直接返回 } #ifdef _WIN32 char *localappdata = getenv("LOCALAPPDATA"); if (localappdata != NULL) { snprintf(conf_path, sizeof(conf_path), "%s/.conf.json", localappdata); } else { strncpy(conf_path, ".conf.json", sizeof(conf_path)-1); conf_path[sizeof(conf_path)-1] = '\0'; // 确保字符串终止 } #else char *home = getenv("HOME"); if (home != NULL) { snprintf(conf_path, sizeof(conf_path), "%s/.conf.json", home); } else { strncpy(conf_path, ".conf.json", sizeof(conf_path)-1); conf_path[sizeof(conf_path)-1] = '\0'; } #endif return conf_path; }
2. 修改代码中引用CONFFILE的地方
将所有CONFFILE替换为get_conf_file_path():
- 修改fexists调用:
if (!fexists(get_conf_file_path())) { msg = "Do you want to save data to config file? (Y/n) [n] : "; }
- 修改create_config中的文件路径:
int create_config(struct config cfg) { struct json_object *jsonobj = json_object_new_object(); json_object_object_add(jsonobj, "a", json_object_new_string(cfg.a)); json_object_object_add(jsonobj, "b", json_object_new_string(cfg.b)); json_object_object_add(jsonobj, "c", json_object_new_string(cfg.c)); const char *conf_path = get_conf_file_path(); int retval = json_object_to_file_ext(conf_path, jsonobj, JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY); printf("Err: %s\n", json_util_get_last_err()); return retval; }
3. 额外修复main中的变量问题
在最小复现程序的main函数中,getchar()的赋值目标未提前声明,需要修正:
int main(){ char *msg = "Do you want to create conffile? (y/n) "; if (!fexists(get_conf_file_path())) { msg = "Do you want to overwrite conffile? (y/n) "; } printf("%s", msg); char ans = getchar(); // 提前声明变量ans if ((ans == 'y') || (ans == 'Y')){ char *a = "vala"; char *b = "valb"; char *c = "valc"; struct config cfg = {a, b, c}; printf("%d", create_config(cfg)); } }
内容的提问来源于stack exchange,提问作者Jai A P
相关产品推荐
相关产品推荐

