2012-11-24 48 views
1

我試圖寫一個類從網站得到一些C++數據使用捲曲。下面是該類的示例(有一個Curl * curl_數據成員,rawData_是一個字符串)。這段摘錄來自實現文件,所有函數都在頭文件中聲明。的libcurl /捲曲C++內存設計缺陷

MyClass::MyClass() 
{ 
    curl_global_init(CURL_GLOBAL_ALL); 
    curl_ = curl_easy_init(); 

    curl_easy_setopt(curl_, CURLOPT_URL, 
       "http://www.google.com"); 
    curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, &MyClass::writeCallback); 

} 

MyClass::~MyClass() 
{ 
    curl_easy_cleanup(curl_); 
    curl_global_cleanup(); 
} 

size_t MyClass::writeCallback(char* buf, size_t size, size_t nmemb, void* up) 
{ 
    //buf is a pointer to the data that curl has for us 
    //size*nmemb is the size of the buffer 
    for (size_t c = 0; c<size*nmemb; ++c) 
    { 
     cerr << c << endl; 
     rawData_.push_back(buf[c]); 
    } 
    return size*nmemb; //tell curl how many bytes we handled 
} 

void MyClass::makeCall() 
{ 
    curl_easy_perform(curl_); 
} 

當我創建一個MyClass的實例並調用makeCall時,writeCallBack函數中存在一個segfault。也就是說,buf看起來大小爲0(當c = 0時,它在buf [c]的調用中斷開)。任何幫助表示讚賞

+0

你是否測試'BUF == this'? –

+0

這是我應該擔心的事嗎?據我所知,'buf'是網絡傳入的東西;它應該基本上是來自網站的數據。 – GuestUser11111

+0

我的意思是,對於C++類方法,可以認爲'this'是靜態C風格函數的隱含的第一個參數。如果curl正在調用你提供的回調,就好像它是一個C樣式函數(它是),至少調用約定不是C++在調用類方法時所期望的,並且未定義的事情發生。 –

回答

4

參數curl_easy_setoptCURLOPT_WRITEFUNCTION應該是size_t function(char *ptr, size_t size, size_t nmemb, void *userdata)類型。這是一個「乾淨的」C函數,而不是一種方法。

但就我所看到的,你傳遞一個非靜態方法的地址。所以它不會有正確的簽名(我猜它是非靜態的,因爲你在裏面使用rawData_)。

現在,curl_easy_setopt並不真正關心 - 它需要你給它什麼。但是當它調用函數時會發生不好的事情。

我的建議是要申報writeCallback爲靜態的(甚至是作爲非會員朋友)和(使用curl_easy_setoptCURLOPT_WRITEDATA)的用戶數據設置爲this。然後,您可以將userdata參數投射到MyClass並在該函數內部使用它。

+0

謝謝!這工作。 – GuestUser11111

+0

不幸的是curl_easy_setopt是一個可變參數函數,所以不能檢查函數參數是否正確,否則編譯器肯定會給出一個關於不能轉換size_t(X :: *)的錯誤。 (char *,size_t,size_t,void *)'到'size_t(*)(char *,size_t,size_t,void *)'。 –

0

在libcurl手冊頁curl_easy_setopt中解釋了CURLOPT_WRITEFUNCTION,它聲明回調可能在某些情況下用「零大小」調用,例如指示空響應。在這種情況下,至少size*nmemb的產品應該爲零,因此您的循環從不輸入空緩衝區,所以您應該在那裏安全。

然而,它也描述了參數CURLOPT_WRITEFUNCTION作爲拍攝功能與給定的參數,而不是一個C++成員函數。這很可能是回調成員函數體內的隱性this指針被解釋爲buf。它只是恰巧,this(內部類狀態)解除引用首次在同一線路上的碰撞:rawData_.push_back(buf[c])

真的很快,嘗試將您的類成員函數回調轉換爲靜態函數回調(即不再是MyClass的成員)。這應該工作。然後,你可以選擇使用此功能作爲friendMyClass,或者你可以代理類成員函數的調用,如果您通過適當的this指針CURLOPT_WRITEDATA選項與curl_easy_setopt設置當你的回調,讓你的靜態非成員函數通過適當的指向類對象的指針調用適當的C++類方法。