libcurl使用需先调用curl_global_init()一次且仅一次,否则curl_easy_init()返回nullptr;下载须设超时、检查http状态码、二进制模式写文件、正确处理重定向,链接时注意运行时库匹配。
libcurl 初始化失败:curl_global_init() 必须调用且只能调一次
很多初学者一上来就 curl_easy_init(),结果返回 nullptr,却找不到原因。根本问题常是漏掉全局初始化,或在多线程环境下重复调用 curl_global_init() 导致未定义行为。
- 必须在程序启动时(如
main()开头)调用curl_global_init(CURL_GLOBAL_DEFAULT),且仅一次 - Windows 下若用 OpenSSL,还需确保
libeay32.dll和ssleay32.dll(或新版libcrypto-*.dll)在 PATH 或可执行目录中,否则curl_global_init()可能静默失败 - 不建议在 DLL 的
DLL_PROCESS_ATTACH中调用它——多个模块各自初始化会冲突;统一由主程序负责 - 对应地,退出前应调用
curl_global_cleanup(),但实际项目中常省略(进程结束自动释放),不过单元测试里不清理会导致 ASan 报告内存泄漏
下载文件时卡住或超时:默认无超时 + 无进度回调易误判成功
curl_easy_perform() 默认会无限等待服务器响应,尤其遇到 DNS 慢、TCP 连接挂起、或服务器不发响应头时,看起来就像“卡死”。更隐蔽的问题是:即使返回 CURLE_OK,也可能只写入了 0 字节(比如 404 页面被当成文件内容)。
- 务必设置
curl_easy_setopt(handle, CURLOPT_TIMEOUT, 30L)(单位秒),对大文件还可加CURLOPT_CONNECTTIMEOUT - 用
CURLOPT_WRITEFUNCTION自定义写入逻辑,而非依赖CURLOPT_WRITEDATA直接写 FILE* —— 否则无法捕获写入失败(如磁盘满) - 加上
CURLOPT_NOBODY+CURLOPT_HEADERFUNCTION预检 HTTP 状态码,避免下载错误页;或者下载后检查CURLINFO_RESPONSE_CODE - 示例片段:
long http_code = 0;<br>curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &http_code);<br>if (http_code != 200) { /* 处理非200 */ }
二进制文件损坏:文本模式打开文件 + 缺少 CURLOPT_FOLLOWLOCATION 安全限制
用 fopen("out.bin", "w") 写下载内容,在 Windows 上会把 \n 自动转成 \r\n,导致图片、ZIP 等二进制文件损坏。另一个常见坑是重定向处理不当:有些资源返回 302 跳转到 CDN 地址,但默认 CURLOPT_FOLLOWLOCATION 关闭,结果下回来的是 HTML 重定向页面。