ファイルからWebアドレスを読み取り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: *** [実行] 中止されました
これは、最初のスレッドが終了した後に発生します。メモリに間違いがあるに違いないことはわかっていますが、なぜこのエラーが発生するのかわかりません。ここで何か不足していますか?また、他のヒントも高く評価されています!