curl_easy_init 后必须检查返回值是否为 nullptr,否则直接解引用会导致段错误;设置 URL 和回调函数时需确保 CURLOPT_URL 和 CURLOPT_WRITEFUNCTION 不遗漏;POST 请求要手动设置 Content-Type 和数据长度;每个 easy handle 需调用 curl_easy_cleanup 且不可跨线程复用。

curl_easy_init 之后必须检查返回值是否为 nullptr
libcurl 的初始化函数 curl_easy_init 在内存不足、内部初始化失败或 libcurl 未正确链接时会直接返回 nullptr。很多新手直接解引用就 crash,错误现象是程序在 curl_easy_setopt 前就段错误。
- 务必在调用
curl_easy_setopt或curl_easy_perform前加判断:if (!curl) { /* 处理错误 */ } - 常见遗漏场景:交叉编译环境(如 Android NDK)下未链接
-lcurl,或动态库路径未设好,curl_easy_init看似成功实则返回空指针 - Windows 下若混用不同 CRT(如 /MD 和 /MT),也可能导致
curl_easy_init返回空——这不是代码问题,而是链接时的 ABI 不兼容
设置 URL 和回调函数时别漏掉 CURLOPT_URL 和 CURLOPT_WRITEFUNCTION
发送 HTTP 请求最简路径需要至少两个关键选项:目标地址和响应体接收方式。漏掉 CURLOPT_URL 会触发 CURLE_URL_MALFORMAT;不设 CURLOPT_WRITEFUNCTION(或 CURLOPT_WRITEDATA)会导致响应体被丢弃,curl_easy_perform 可能静默成功但你啥也没拿到。
-
CURLOPT_URL必须是 C 风格字符串(const char*),传std::string.c_str()要确保该 string 生命周期覆盖整个请求过程 - 推荐用自定义
WRITEFUNCTION把响应写入std::string或std::vector<uint8_t></uint8_t>,而不是依赖CURLOPT_FILE写文件——后者容易因路径权限、编码、换行符出问题 - 示例回调签名必须匹配:
size_t write_callback(void* ptr, size_t size, size_t nmemb, void* userdata);返回值是真正写入的字节数,不能硬写return size * nmemb,否则 libcurl 会认为写失败而中止传输
POST 请求要手动设 Content-Type 和数据长度
用 CURLOPT_POST 或 CURLOPT_CUSTOMREQUEST 发 POST 时,libcurl 不会自动加 Content-Type 头,也不会帮你算 Content-Length。服务端常因缺少 Content-Type 直接拒收,或把 JSON 当纯文本解析失败。
- JSON 请求必设:
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers),其中headers是struct curl_slist*,包含"Content-Type: application/json" - 若用
CURLOPT_POSTFIELDS,libcurl 会自动设Content-Length;但若用CURLOPT_READFUNCTION流式上传,则必须手动调用curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, len),否则服务器收不到数据 - 注意:设了
CURLOPT_POSTFIELDS后不能再设CURLOPT_POST——两者冲突,后者会被忽略,且可能引发未定义行为
记得调用 curl_easy_cleanup 并避免跨线程复用 easy handle
每个 curl_easy_init 对应一个独立的 easy handle,它不是线程安全的。不清理会泄漏内存和 socket 描述符;在线程间传递 handle 可能导致崩溃或诡异超时。
立即学习“C++免费学习笔记(深入)”;
-
curl_easy_cleanup必须成对出现,哪怕curl_easy_perform返回失败也要调用 - 不要在多个线程里共用同一个 handle;如需并发请求,请为每个线程创建独立 handle,或改用 multi interface(
curl_multi_*) - multi interface 虽支持并发,但它的 callback 机制更复杂,初学者容易在
curl_multi_add_handle/remove_handle时搞错生命周期,反而比多个 easy handle 更难 debug
实际用起来最麻烦的从来不是怎么发请求,而是错误码含义模糊、回调返回值规则隐蔽、以及 handle 生命周期和线程模型那几处边界条件。稍微一跳步,就卡在 CURLE_SEND_ERROR 或 CURLE_PARTIAL_FILE 上半天。











