gpt4 book ai didi

c - 多线程下载程序中的段错误

转载 作者:太空宇宙 更新时间:2023-11-03 23:33:05 24 4
gpt4 key购买 nike

我正在尝试编写一个简单的程序。它应该从 stdin 读取链接,并在单独的线程中下载这些链接。我编写了以下代码,但遇到了段错误。谁能猜出这是为什么?

#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* memcpy */
#include <curl/curl.h>
#include <pthread.h>
#define NUMTHREADS 3

struct downloadfile {
char *filename;
FILE *stream;
};

pthread_mutex_t mutex;

/* writedata: custom fwrite for curl writefunction */
static size_t writedata(void *buffer, size_t size, size_t nmemb, void *stream)
{
struct downloadfile *out = (struct downloadfile *) stream;
if (out && !out->stream) {
out->stream = fopen(out->filename, "w");
if (!out->stream)
return -1; /* can't open file to write */
}
return fwrite(buffer, size, nmemb, out->stream);
}

/* getfilename: gets a file's name from a link. */
char *getfilename(const char *link)
{
const char *fnstart = NULL; /* start of filename*/
size_t len = 0; /* length of filename*/

for ( ; *link != '\0'; ++link) {
if (*link == '/') {
fnstart = link + 1;
len = 0;
} else {
++len;
}
}

char *filename = malloc(len + 1);
memcpy(filename, fnstart, len);
filename[len] = '\0';
return filename;
}

/* downloadthread: get a line from stdin, and try to donwload it.*/
void *downloadthread(void *ignored)
{

puts("in a download thread");
CURL *curl;
curl = curl_easy_init();
ssize_t read; /* number of characters read from a line */

if (!curl) { /* couldn't get curl handle */
fputs("Couldn't get curl handle", stderr);
pthread_exit(NULL);
}

for (;;) { /* readline and download loop */
size_t n; /* argument to getline */
char *lineptr = NULL; /* argument to getline */
struct downloadfile ofile;

/* I think I need mutex protect the getline, but I am not sure */
pthread_mutex_lock(&mutex);
read = getline(&lineptr, &n, stdin);
pthread_mutex_unlock(&mutex);

if (read == EOF)
break;

ofile.filename = getfilename(lineptr);
curl_easy_setopt(curl, CURLOPT_URL,lineptr);

/* follow http redirects */
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION ,1L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writedata);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ofile);

curl_easy_perform(curl);

free(ofile.filename);
free(lineptr);

if (ofile.stream)
fclose(ofile.stream);
}
curl_easy_cleanup(curl);
pthread_exit(NULL);
}

int main()
{
size_t i;
int rc;
pthread_t threads[NUMTHREADS];

curl_global_init(CURL_GLOBAL_ALL);
pthread_mutex_init(&mutex, NULL);

/* fire up threads */
for (i = 0; i < NUMTHREADS; i++) {
rc = pthread_create(&threads[i], NULL, downloadthread, NULL);
if (rc) {
printf("Error, return code from pthread is %d\n", rc);
exit(-1);
}
}

/* join all threads before cleaning up */
for (i = 0; i < NUMTHREADS; i++)
pthread_join(threads[i], NULL);

/* cleanup and exit */
pthread_mutex_destroy(&mutex);
pthread_exit(NULL);
}

编辑:这是 gdb 的输出。它并没有给我太多的想法。

[New Thread 0xb61feb40 (LWP 3778)]
[New Thread 0xb57ffb40 (LWP 3779)]
[New Thread 0xb4ffeb40 (LWP 3780)]
[Thread 0xb61feb40 (LWP 3778) exited]
[Thread 0xb57ffb40 (LWP 3779) exited]
[Thread 0xb4ffeb40 (LWP 3780) exited]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb7b25b40 (LWP 3773)]
0xb7e02310 in fwrite () from /lib/libc.so.6
(gdb) bt
#0 0xb7e02310 in fwrite () from /lib/libc.so.6
#1 0xb7f6dd53 in ?? () from /usr/lib/libcurl.so.4
#2 0xb7f85a5e in ?? () from /usr/lib/libcurl.so.4
#3 0xb7f86bb5 in ?? () from /usr/lib/libcurl.so.4
#4 0xb7f87573 in curl_easy_perform () from /usr/lib/libcurl.so.4
#5 0x08048d99 in downloadthread (ignored=0x0) at downloader.c:91
#6 0xb7f47ce8 in start_thread () from /lib/libpthread.so.0
#7 0xb7e874de in clone () from /lib/libc.so.6

最佳答案

当你声明 struct downloadfile ofile 时,它的 stream 字段被垃圾填充并且可能不是 0。当 ofile 被传递给 writedata 回调(作为调用 curl_easy_perform 的结果),条件 out && !out->stream 因此可能为假并导致 writedata 在未打开的流上调用 fwrite

因此只需将 ofile 声明替换为 struct downloadfile ofile = { 0, 0 };

关于c - 多线程下载程序中的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10752013/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com