我应该写一个机器人从文件中读取网址,并执行GET
请求,该请求再次写入文件。这项工作到目前为止,但该程序始终以"堆栈粉碎错误" 终止。我与多个"消费者"线程,它将完成工作,当所有GET
请求完成并且第一个线程完成时,程序终止。
以下是我的代码:
#include <pthread.h>
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "Socket/msocket.h"
/*
*
*/
#define MAXLINE 512
typedef struct {
char** addr;
long head, tail;
int full, empty, reading;
pthread_mutex_t *mut;
pthread_cond_t *notFull, *notEmpty;
} queue;
typedef struct {
struct queue *q;
int tid;
} arguments;
int queueSize;
int elemCount=0;
int isEmpty;
char file[MAXLINE];
void *readFile(void *args);
void *consume(void *args);
char* parseLine(char*);
char** parseAddr(char*);
queue *queueInit (int);
void queueDelete (queue *q);
void queueAdd (queue *q, char* new);
void queueDel (queue *q, char** out, int *o);
/* main function
argv[0]: program name (here ./bot)
argv[1]: file name (xyz.txt,...)
argv[2]: size of queue
argv[3]: number of client/consumer threads
*/
int main(int argc, char** argv) {
strcpy(file, argv[1]);
queueSize = atoi(argv[2]);
int maxCli = atoi(argv[3]);
printf("-------queueSize: %i--------\n", queueSize);
printf("---------maxCli: %i-------\n", maxCli);
int j=0;
queue *fifo;
pthread_t prod, con[maxCli];
struct timeval tv;
fifo = queueInit(queueSize);
if(fifo == NULL){
printf("queueInit() failed");
exit(1);
}
gettimeofday(&tv, NULL);
double start = (tv.tv_sec) * 1000 + (tv.tv_usec)/1000;
pthread_create(&prod, NULL, readFile, fifo);
while(j<maxCli){
arguments *threadSet = malloc(sizeof(arguments));
threadSet->q = fifo;
threadSet->tid = j+1;
pthread_create(&con[j], NULL, consume, threadSet);
j++;
}
j=0;
pthread_join(prod, NULL);
while(j<maxCli){
pthread_join(con[j], NULL);
j++;
}
double end = (tv.tv_sec) * 1000 + (tv.tv_usec)/1000;
printf("time elapsed: %d\n", end-start);
printf("----------------threads end----------------\n");
queueDelete(fifo);
return (EXIT_SUCCESS);
}
void *readFile(void *q){
FILE *fp = fopen(file, "r");
if(fp==NULL){
printf("fopen() failed");
return;
}
char tmp[MAXLINE];
arguments *threadSet;
queue *fifo;
int k;
fifo = (queue *)q;
while(fgets(tmp, MAXLINE, fp) != NULL){
pthread_mutex_lock(fifo->mut);
if(fifo->full){
printf("producer: queue FULL\n");
pthread_cond_wait(fifo->notFull, fifo->mut);
}
strcpy(tmp, parseLine(tmp));
queueAdd(fifo, tmp);
elemCount++;
printf("producer: added %s\n", tmp);
printf("element count: %i\n", elemCount);
pthread_mutex_unlock(fifo->mut);
pthread_cond_signal(fifo->notEmpty);
usleep(100000 + 100000);
}
fclose(fp);
fifo->reading = 0;
printf("--------------read end---------------\n");
return(NULL);
}
void *consume(void *a){
printf("consume begin\n");
arguments *threadSet;
queue *fifo;
char* c;
int elemNr;
int retValue;
threadSet = (arguments *)a;
fifo = (queue *)threadSet->q;
while(1){
pthread_mutex_lock(fifo->mut);
//printf("---------------consume begin--------------\n");
if(fifo->empty && !fifo->reading){
printf("end\n");
break;
}
if(fifo->empty && fifo->reading){
printf("consumer(%i): queue EMPTY\n", threadSet->tid);
pthread_cond_wait(fifo->notEmpty, fifo->mut);
}
if(!fifo->empty){
queueDel(fifo, &c, &elemNr);
char fname_a[] = "file_";
char* fname_b = malloc(MAXLINE);
snprintf(fname_b, MAXLINE, "<%i>_<%i>.html", elemNr, threadSet->tid);
strcat(fname_a, fname_b);
printf("%s\n", fname_a);
char** args;
args = parseAddr(c);
if( (retValue = askServer(args[0], args[1], fname_a)) < 0){
printf("askServer() failed: %s\n", args[0]);
printf("error value: %i\n", retValue);
return(NULL);
}
elemCount--;
printf("consumer(%i): picked %s\n", threadSet->tid, c);
printf("---------------consume end--------------\n");
}
pthread_mutex_unlock(fifo->mut);
pthread_cond_signal(fifo->notFull);
usleep(200000 + 300000);
}
printf("end thread: consumer(%i)\n", threadSet->tid);
free (threadSet);
return(NULL);
}
char** parseAddr(char* c){
char* args[2];
char* next = strchr(c, '/');
args[1] = malloc(sizeof(char)*MAXLINE);
strcpy(args[1], next);
next[0] = '\0';
args[0] = malloc(sizeof(char)*MAXLINE);
strcpy(args[0], c);
return args;
}
char* parseLine(char* c){
char* next = strchr(c, ' ');
next[0] = '\0';
char* t = next+1;
next = strchr(t, '\n');
if(next != NULL) next[0] = '\0';
strcat(c, t);
return c;
}
queue *queueInit (int size){
queue *q;
q = (queue *)malloc (sizeof (queue));
if (q == NULL) return (NULL);
q->addr = malloc(size);
int i=0;
while(i<size){
q->addr[i] = malloc(sizeof(char)*MAXLINE);
i++;
}
q->empty = 1;
q->full = 0;
q->reading = 1;
q->head = 0;
q->tail = 0;
q->mut = (pthread_mutex_t *) malloc (sizeof (pthread_mutex_t));
pthread_mutex_init (q->mut, NULL);
q->notFull = (pthread_cond_t *) malloc (sizeof (pthread_cond_t));
pthread_cond_init (q->notFull, NULL);
q->notEmpty = (pthread_cond_t *) malloc (sizeof (pthread_cond_t));
pthread_cond_init (q->notEmpty, NULL);
return (q);
}
void queueDelete (queue *q){
pthread_mutex_destroy (q->mut);
free (q->mut);
pthread_cond_destroy (q->notFull);
free (q->notFull);
pthread_cond_destroy (q->notEmpty);
free (q->notEmpty);
int i=0;
while(i<queueSize){
free (q->addr[i]);
i++;
}
free (q->addr);
free (q);
}
void queueAdd (queue *q, char* new){
q->addr[q->tail] = (char*)malloc(sizeof(char));
strcpy(q->addr[q->tail], new);
q->tail++;
if (q->tail == queueSize)
q->tail = 0;
if (q->tail == q->head)
q->full = 1;
q->empty = 0;
return;
}
void queueDel (queue *q, char **out, int *o){
*out = q->addr[q->head];
*o = q->head+1;
q->head++;
if (q->head == queueSize)
q->head = 0;
if (q->head == q->tail)
q->empty = 1;
q->full = 0;
return;
}
我收到错误:
*检测到堆栈粉碎* :./ bot终止 make:*** [run] Aborted
第一个线程完成后会发生这种情况。我知道记忆中一定有错,但我不明白为什么会出现这个错误。我在这里错过了什么吗? 还有其他任何提示都是适用的!
答案 0 :(得分:1)
我很确定你在parseAddr
中有一个错误:
char** parseAddr(char* c){
char* args[2];
...
return args;
}
虽然args[0]
和args[1]
是动态分配的,但args
本身并非如此。返回时,实际将分配指向args
的指针。因为在函数退出后销毁args
数组,尝试访问返回的值将产生未定义的行为。
如果你想这样做,传入一个数组作为函数的一个参数填入,并获得填充它的函数。您还可以动态分配数组(例如char** args; args = malloc(sizeof(char*)*2);
。
如果这样做无效,请在valgrind
下运行它可能有助于确定错误。
答案 1 :(得分:0)
这里也可能存在问题:
void queueAdd (queue *q, char* new){
q->addr[q->tail] = (char*)malloc(strlen(new)+1);
应更改为:
thread.c: In function ‘parseAddr’:
thread.c:189:5: warning: function returns address of local variable [-Wreturn-local-addr]
return args;
^
否则,malloc在'strlen(new)+1'字节被转移到分配区域之前只分配一个字节。
你还应该解决这种警告(在上面的另一个答案中已经提到过):
<!-- Facebook Pixel Code -->
{literal}
<script>
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
document,'script','//connect.facebook.net/en_US/fbevents.js');
{/literal}
fbq('init', 'pixel_code_here');
fbq('track', "PageView");
{$product_page_facebook_tracking['js_event']}
</script>
<noscript>
<img height="1" width="1" style="display:none"
src="https://www.facebook.com/tr?id=pixel_code_here&ev=PageView&noscript=1"
/>
</noscript>
<!-- End Facebook Pixel Code -->
简要描述您的环境也可以帮助人们解决您的问题。