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

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
  1. 修改只读内存:getenv()返回的是指向环境变量的只读内存区域,直接用strcat()修改该区域会触发未定义行为。
  2. 重复拼接路径:每次引用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 11:45:38