最近再寫一個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] = {''}; 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 |
段錯誤
看來,寬鬆意為著需要更加嚴謹。沒有條條框框的約束,得做好自我約束。