堆栈粉碎错误

时间:2016-05-22 10:51:24

标签: c multithreading stack-smash

我应该写一个机器人从文件中读取网址,并执行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

第一个线程完成后会发生这种情况。我知道记忆中一定有错,但我不明白为什么会出现这个错误。我在这里错过了什么吗? 还有其他任何提示都是适用的!

2 个答案:

答案 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 -->

简要描述您的环境也可以帮助人们解决您的问题。