簡體   English   中英

為什么libcurl在對curl_easy_perform()的調用上出現段錯誤?

[英]Why is libcurl segfaulting on this call to curl_easy_perform()?

在我為負載測試站點編寫的HTTP Flooder中使用libCURL時,出現了段錯誤。

這是相關的代碼: https : //gist.github.com/AppleDash/a26e0ce0b138cd9eacd2 (在此處粘貼有點大。)

這是它隔離段所在行的鏈接: https ://gist.github.com/AppleDash/a26e0ce0b138cd9eacd2#file-httpflood-improved-c-L57

這是段錯誤的回溯:

#0  0x00007ffff760d65b in fwrite () from /usr/lib/libc.so.6
#1  0x00007ffff79656d8 in ?? () from /usr/lib/libcurl.so.4
#2  0x00007ffff797a76b in ?? () from /usr/lib/libcurl.so.4
#3  0x00007ffff7984349 in ?? () from /usr/lib/libcurl.so.4
#4  0x00007ffff7984b11 in curl_multi_perform () from /usr/lib/libcurl.so.4
#5  0x00007ffff797b977 in curl_easy_perform () from /usr/lib/libcurl.so.4
#6  0x0000000000400f42 in flood (structPointer=0x7fffffffe060) at httpflood.c:57
#7  0x00007ffff7bc5124 in start_thread () from /usr/lib/libpthread.so.0
#8  0x00007ffff768b4bd in clone () from /usr/lib/libc.so.6

我不明白為什么這個電話會引起段錯誤。 有任何想法嗎?

我知道您只打算提供一小部分相關代碼,但由於我覺得這里需要上下文,因此在這里提供了全部內容。 (事實上​​,它是從許多線程等運行的。)

這是你的問題:

for (i = 0; i < threadnum; i++) {
    struct flood_data ddosData;
    memset(&ddosData, 0, sizeof(struct flood_data));
    ddosData.url = url;
    ddosData.proxy = getProxy();
    pthread_create(&threads[i], NULL, flood, (void *)&ddosData);
}

您要在堆棧上分配單個struct flood_data實例,並將其同時傳遞給所有新線程。 每次迭代循環時,您都會覆蓋同一實例,而從較早的迭代生成的線程可能會嘗試從中讀取同一實例。 主要的不確定行為。

正確的方法是為每個線程動態分配一個單獨的實例:

for (i = 0; i < threadnum; i++) {
    struct flood_data *ddosData = calloc(1, sizeof(*ddosData));
    ddosData->url = url;
    ddosData->proxy = getProxy();
    pthread_create(&threads[i], NULL, flood, ddosData);
}

...

void *flood(void *structPointer) {
    struct flood_data *data = structPointer;
    char *bootable = data->url;
    char *proxy = data->proxy;
    free(data);
    ...
}

正如評論中指出的那樣,您還需要檢查系統調用是否失敗。 您應該驗證對fopen()所有調用都成功,因為您很可能會達到在進程中打開的文件描述符的最大數目。 而不是將文件打開到/dev/null ,為什么不使用CURLOPT_WRITEFUNCTION選項設置無操作寫功能呢?

static size_t noop_write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
{
    // Do nothing
    return size * nmemb;
}

...

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &noop_write_callback);
// No need to call fopen("/dev/null") or set CURLOPT_WRITEDATA now

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM