libcurl中使用curl_easy_getinfo 产生段错误分析

简介:
最近再写一个hsf的代理程序。需要使用libcurl与后端的nginx通信。程序编写过程中遇到一个蹊跷的问题。
调用 code = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &rsp_code); 后会报段错误。

示例代码如下:


static int http_proxy(std::string domain, std::string path, std::string params, std::string &rsp_cont, std::string host = ""){
    string url;
    int rsp_code; //此处设置为int类型 会有段错误。如果long类型没问题。
    char str_rsp_code[5] = {'\0'};
    CURLcode code;
    CURL* curl;
    curl_slist *headers = NULL;
    curl = curl_easy_init();
 
    curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
    curl_easy_setopt(curl, CURLOPT_USERAGENT, "hsfproxy");
    curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, on_write);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&rsp_cont); 
    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5);
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5);
    code = curl_easy_perform(curl);
    code = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &rsp_code);
    curl_easy_cleanup(curl);
    sprintf(str_rsp_code,"%d",rsp_code);
    log("curl: http code["+ (std::string)str_rsp_code +"] url[" + (std::string)url + "] domain["+ domain +"]", __FILE__, __LINE__, __FUNCTION__, LOG_VERBOSE);
    return 1;
}

问题:
int rsp_code;
code = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &rsp_code);
当rsp_code设置为int类型 会有段错误。如果long类型没问题。

分析:
下载了libcurl的代码,查找原因。
原来curl_easy_getinfo的实现使用了可变参数。即,在编译时不进行参数个数和参数类型检测。这样,在使用这个函数时,无论你传入的类型是int还是long,都不会报错。虽然,它要求的是long类型。不过,在赋值的时候,他可是按long类型赋值的。这样就导致栈被破坏了。当然就报段错误了。
相关代码如下:


#undef curl_easy_getinfo
CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
{
  va_list arg;
  void *paramp;
  CURLcode ret;
  struct SessionHandle *data = (struct SessionHandle *)curl;
 
  va_start(arg, info);
  paramp = va_arg(arg, void *);
 
  ret = Curl_getinfo(data, info, paramp);
 
  va_end(arg);
  return ret;
}

验证:
编写了示例代码,验证了假设。注意此代码在32位操作系统上不会报错,在64位操作系统上会报段错误。注意只有在int和long类型长度不一致时才会出现段错误。如在64位操作系统。


#include <iostream>
#include <string>
#include <cstdarg>
 
using namespace std;
 
void f(char chr, ...){
        long value = 202;
        long *paramp;
        va_list arg_ptr;
        va_start(arg_ptr, chr);
        paramp = va_arg(arg_ptr, long *);
        va_end(arg_ptr);
        *paramp = value;
}
int main(){
        string a;
        int p=0;
        string b;
        a = "a";
        b = "b";
        f('a',&p);
        cout << "p value " << p << endl;
        cout << "a value " << a << endl;
        cout << "b value " << b << endl;

输出:


[hailong.xhl@v101080140 test]$ ./test
p value 202
b value b
段错误

看来,宽松意为着需要更加严谨。没有条条框框的约束,得做好自我约束。


目录
相关文章
|
数据采集 API C语言
如何在C程序中使用libcurl库下载网页内容
爬虫是一种自动获取网页内容的程序,它可以用于数据采集、信息分析、网站监测等多种场景。在C语言中,有一个非常强大和灵活的库可以用于实现爬虫功能,那就是libcurl。libcurl是一个支持多种协议和平台的网络传输库,它提供了一系列的API函数,可以让开发者方便地发送和接收HTTP请求。
194 0
如何在C程序中使用libcurl库下载网页内容
|
1月前
jetson错误(三):E: 有未能满足的依赖关系。请尝试不指明软件包的名字来运行“apt --fix-broken install”(也可以指定一个解决办法
在NVIDIA Jetson平台上遇到“未能满足的依赖关系”错误时,可以通过运行“sudo apt-get -f install”或“sudo apt-get --fix-broken install”命令来解决。
190 1
|
测试技术 C++ Windows
Windows下VS2015编译并使用libcurl.lib静态库(curl:http客户端库c++版本)
Windows下VS2015编译并使用libcurl.lib静态库(curl:http客户端库c++版本)
1223 0
|
Web App开发 iOS开发
使用curl来调试你的应用
我们在客户端开发过程中总免不了和后端进行api对接,有时候需要对返回的数据格式进行调试,有时候每次运行客户端来发送请求,这个未免效率太低,这里就来介绍一个好用的工具--curl。 curl curl是一个向服务器传输数据的工具,它支持http、https、ftp、ftps、scp、sftp、tftp、telnet等协议,这里只针对http进行讲解一些常用的用法,具体安装请自行搜索。
1172 0