Ich soll einen Bot schreiben, der Webadressen aus Datei liest und eine GET
Anfrage ausführt, die wieder in eine Datei geschrieben wird. Dies funktioniert soweit, aber das Programm endet immer mit einem "Stack Smashing Error". Ich arbeite mit mehreren "Consumer" -Threads, die den Job erledigen, und wenn alle GET
Anfragen erledigt sind und der erste Thread fertig ist, wird das Programm beendet.Stack smashing error
Unten ist mein Code:
#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;
}
Fehler Ich erhalte:
* Stapel * erkannt Zerschlagung: ./bot beendet make: *** [run] Abgebrochen
Dies geschieht, nachdem der erste Thread beendet ist. Ich weiß, dass es einen Fehler in der Erinnerung geben muss, aber ich verstehe nicht, warum ich diesen Fehler bekomme. Fehle ich hier etwas? Auch andere Tipps sind erwünscht!
Wie wäre es nur mit wget? – nwp
Warum Zeiger auf die thread-related Elemente der Warteschlangenstruktur verwenden? Warum nicht einfach Instanzen dieser Typen direkt in die Struktur einbetten? Dies ist jedoch nur eine Quelle von Speicherverlust; Im Code sind andere sichtbar. Aber Speicherlecks sind nicht direkt eine Ursache für Stack-Zerschlagung - die Probleme sind etwas tangential zu Ihrem Hauptproblem. –
@nwp weil wir es so machen sollen. Unser Lehrer hat uns eine Klasse für die GET-Anfrage gegeben, die er geschrieben hat, und wir müssen Code um ihn herum sortieren. –