CURL调用代码段错误求助:chunk对象内存被覆盖问题排查
CURL调用API时
curl_easy_getinfo导致内存指针失效的问题排查 我写了一段用C语言CURL调用API的代码,运行时触发段错误。通过GDB调试发现错误出在*response = strdup(chunk.memory);这一行,此时chunk对象的memory指针指向不可访问的内存地址:
- 执行
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &res);之前,chunk状态正常,memory存储着预期的JSON响应内容; - 执行该行后,
chunk的memory指针被覆盖为无效地址(0x557b00000000)。chunk是局部变量,找不到被覆盖的原因,请求协助排查。
代码示例
#include <stddef.h> #include <stdlib.h> #include <string.h> #include <curl/curl.h> #define API_BASE_PATH "127.0.0.1/api/v2/" #define API_INFO "lcd/info" typedef enum { Get, //!< GET method Post, //!< POST method Patch //!< PATCH method } Api_Method; struct MemoryStruct { char *memory; size_t size; }; size_t WriteData(void *contents, size_t size, size_t nmemb, void *userp) { size_t realsize = size * nmemb; struct MemoryStruct *mem = (struct MemoryStruct *)userp; mem->memory = (char*)realloc(mem->memory, mem->size + realsize + 1); memset(mem->memory, 0, mem->size + realsize + 1); if(mem->memory == NULL) { /* out of memory! */ printf("not enough memory (realloc returned NULL)\n"); return 0; } memcpy(&(mem->memory[mem->size]), contents, realsize); mem->size += realsize; mem->memory[mem->size] = 0; return realsize; } int callApi(const char* api, char* authorization_token, char* params, char* body, char** response, Api_Method method) { CURL* curl; CURLcode res; MemoryStruct chunk; // Initialize objects memset(&chunk,0,sizeof(MemoryStruct)); curl_global_init(CURL_GLOBAL_ALL); curl = curl_easy_init(); // Call the API prepending the base path int api_length = strlen(API_BASE_PATH) + strlen(api) + (params != NULL ? strlen(params) : 0) + 1; char* api_string = (char*)malloc(api_length); memset(api_string, 0, api_length); snprintf(api_string, api_length, "%s%s%s", API_BASE_PATH, api, params != NULL ? params : ""); chunk.memory = (char*)malloc(1); chunk.size = 0; curl_easy_setopt(curl, CURLOPT_URL, api_string); switch (method) { case Post: curl_easy_setopt(curl, CURLOPT_POST, true); break; case Patch: curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PATCH"); break; default: break; } // Set the writing callback function curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteData); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); if ((res = curl_easy_perform(curl)) != CURLE_OK ) { printf("curl failed: %s\n", curl_easy_strerror(res)); } else { res = CURLE_OK; curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &res); curl_easy_cleanup(curl); if (response != NULL) { *response = strdup(chunk.memory); } } curl_global_cleanup(); if (chunk.memory != NULL) { free(chunk.memory); } if (api_string != NULL) { free(api_string); } return 0; } int main(int argc, char **argv) { char* response = NULL; // Call the API callApi(API_INFO, NULL, NULL, NULL, &response, Get); printf("%s\n", response); return 0; }
调试信息
执行curl_easy_getinfo前chunk状态:
{memory = 0x557bcc43a750 "{\"cpf\":\"MYCPF\",\"software_version_tag\":\"1.1.0\",\"di1\":{\"id\":\"DI_1\",\"type\":\"input\",\"status\":0,\"label\":\"D.I. 1\"},\"autologin_enabled\":true,\"data\":{\"min\":0,\"usage\":0,\"eta\":0,\"max\":0},\"acti"..., size = 1920}
执行curl_easy_getinfo后chunk状态:
{memory = 0x557b00000000 <error: Cannot access memory at address 0x557b00000000>, size = 1920}
问题根源
代码存在参数类型不匹配的致命错误:curl_easy_getinfo获取CURLINFO_RESPONSE_CODE时,要求传入long*类型的指针,但你传入的是CURLcode*类型的&res。
在64位系统中,long通常占8字节,而CURLcode本质是int(占4字节)。当curl_easy_getinfo尝试向这个地址写入8字节的响应码时,会越界覆盖栈上相邻的内存区域——恰好chunk是和res相邻的局部变量,导致chunk.memory指针被破坏,变成无效地址。
修复方案
- 核心修复:单独声明
long类型变量存储响应码,避免复用CURLcode变量:
if ((res = curl_easy_perform(curl)) != CURLE_OK ) { printf("curl failed: %s\n", curl_easy_strerror(res)); } else { long response_code; curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); curl_easy_cleanup(curl); if (response != NULL) { *response = strdup(chunk.memory); } }
- 额外优化建议:
WriteData中memset整个新分配内存的操作多余,只需在最后给字符串末尾加\0即可,减少不必要的内存操作;curl_global_init应放在程序启动时调用一次,而非每次调用callApi都执行,避免重复初始化开销;- 完善错误处理逻辑:比如
malloc/realloc失败时,要及时清理已分配的资源,避免内存泄漏; callApi的返回值应返回实际的错误码或HTTP响应码,而非固定返回0,方便调用方判断结果。
内容的提问来源于stack exchange,提问作者bui3
相关产品推荐
相关产品推荐

