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

URL编码函数get_encoded_string偶现重复返回旧值问题求助

问题分析:URL编码器偶现返回旧值的原因

问题背景

实现的URL编码器中,get_encoded_string函数偶发返回上一次调用的结果。例如调用call_api("api_key", "pokerName","message")时,该函数先后处理"pokerName"和"message",但有时会两次返回"pokerName"。

相关代码

call_api方法

char* call_api(const char* api_key, const char* pokerName, const char* message) {

CURL* curl;
CURLcode res;
curl = curl_easy_init();

char errbuf[CURL_ERROR_SIZE];

/* string builder */
char url[MAX_MESSAGE_SIZE];
snprintf(
    url,
    sizeof(url),
    "%s%s%s%s%s%s",
    "http://xdroid.net/api/message?k=",
    api_key,
    "&t=",
    get_encoded_string(pokerName),
    "&c=",
    get_encoded_string(message));

curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
struct curl_slist* headers = NULL;
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
const char* data = "";
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
res = curl_easy_perform(curl);

if (res == CURLE_OK) {
    return "success";
}
else {
    return errbuf;
}
curl_easy_cleanup(curl);
}

get_encoded_string函数

char* get_encoded_string(char* string_to_encode) {

CURL* curl = curl_easy_init();

/* convert a string into a URL encoded string */
char* encoded_message = curl_easy_escape(curl, string_to_encode, 0);
curl_free(encoded_message);
curl_easy_cleanup(curl);
return encoded_message;
}

问题原因分析

  • 核心错误:返回已释放的野指针
    get_encoded_string中,curl_easy_escape会在堆上分配内存存储编码后的字符串,并将地址赋值给encoded_message。但函数紧接着调用curl_free(encoded_message)释放了这块内存,之后却返回这个已经失效的指针。此时指针指向的是已被释放的内存区域,属于典型的野指针。
  • 偶现旧值的本质
    被释放的内存不会立刻被系统回收或覆盖:当第二次调用get_encoded_string时,如果新分配的内存恰好和第一次释放的地址重合,就会覆盖旧值;但如果内存未被覆盖、或后续分配的内存地址不同,原内存区域残留的旧数据就会被返回,这就是问题偶发的根本原因。
  • 额外风险提示
    这种野指针行为还可能导致程序崩溃、内存损坏等更严重的问题,返回旧值只是其中一种表现。

修复建议

修改get_encoded_string,不要提前释放编码后的字符串,将其返回给调用者,由调用者在使用完成后负责释放:

char* get_encoded_string(char* string_to_encode) {
    CURL* curl = curl_easy_init();
    if (!curl) {
        return NULL; // 处理curl初始化失败的情况
    }
    char* encoded_message = curl_easy_escape(curl, string_to_encode, 0);
    curl_easy_cleanup(curl);
    return encoded_message;
}

然后在call_api中,使用完编码字符串后手动释放内存:

char* encoded_pokerName = get_encoded_string(pokerName);
char* encoded_message = get_encoded_string(message);
snprintf(
    url,
    sizeof(url),
    "%s%s%s%s%s%s",
    "http://xdroid.net/api/message?k=",
    api_key,
    "&t=",
    encoded_pokerName,
    "&c=",
    encoded_message);
// 使用完成后释放内存
curl_free(encoded_pokerName);
curl_free(encoded_message);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 16:05:38