App*_*ash 0 c libcurl segmentation-fault
在我为我的网站进行负载测试而编写的HTTP flooder中使用libCURL时,我遇到了段错误.
以下是相关代码:https://gist.github.com/AppleDash/a26e0ce0b138cd9eacd2(这里要粘贴一点点.)
这是一个链接到它是segfaulting的行: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
Run Code Online (Sandbox Code Playgroud)
我不明白为什么这个电话会导致段错误.有任何想法吗?
我知道你的意思是只提供相关代码的一小部分样本,但在这里我提供了整个事情,因为我觉得这里需要上下文.(事实上,它是从许多线程运行的.)
这是你的问题:
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);
}
Run Code Online (Sandbox Code Playgroud)
您在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);
...
}
Run Code Online (Sandbox Code Playgroud)
正如评论中指出的那样,您还需要检查系统调用是否失败.您应该验证所有调用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
Run Code Online (Sandbox Code Playgroud)