博客專欄

        EEPW首頁 > 博客 > libcurl中使用curl_easy_getinfo 產生段錯誤分析

        libcurl中使用curl_easy_getinfo 產生段錯誤分析

        發布人:電子禪石 時間:2025-03-20 來源:工程師 發布文章

        踩棧的典型案例:

        最近再寫一個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]$ ./testp value 202b value b段錯誤


        看來,寬松意為著需要更加嚴謹。沒有條條框框的約束,得做好自我約束。



        *博客內容為網友個人發布,僅代表博主個人觀點,如有侵權請聯系工作人員刪除。



        關鍵詞: curl

        技術專區

        關閉
        主站蜘蛛池模板: 大埔区| 象州县| 和平区| 开化县| 阳泉市| 青川县| 开鲁县| 宁化县| 梁平县| 大厂| 轮台县| 积石山| 城固县| 大关县| 兴义市| 潞西市| 汨罗市| 定远县| 页游| 尖扎县| 盐亭县| 寿宁县| 吉木萨尔县| 阳新县| 嘉兴市| 普兰县| 尉氏县| 达日县| 丰顺县| 海原县| 怀宁县| 五指山市| 盐山县| 高淳县| 东源县| 慈利县| 德昌县| 江津市| 江口县| 来宾市| 铜梁县|