线程功能故障,输出不完整和分段错误

时间:2018-06-07 15:55:01

标签: c struct segmentation-fault pthreads

以下代码应该创建一个Producer线程和一个Consumer线程。 Producer创建随机数,将它们添加到循环缓冲区(push_back()),然后将它们写入名为prod_out.txt的输出txt中。消费者通过弹出它们(pop_front())“消耗”这些数字,然后将它们写在名为cons_out.txt的输出txt中。对于这样的调用./a.out 1 1 10 20 1,争论如下:将有1个生产者,1个消费者,10个是循环缓冲区的容量,将生成20个随机数,并且rand_r的种子为1。

如果缓冲区的容量小于要生成的随机数的大小,程序只在消费者的txt中写入9个数字,而生产者的txt就好了。如果它们相同则不会创建消费者的txt,并且生产者的txt错过一个数字(即最后一个数字,就像消费者txt在容量小于生成的数字时所做的那样)。

这是主要功能

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include "prodcons.h"


FILE * fp;
int rc;
circular_buffer* cb;
int fileW, my_random;
pthread_mutex_t Mutex;
pthread_cond_t Condition;
args* t_args;

void* Producers(void* fargs){
printf("I am Producer and I am not locked\n");
args* f_args= fargs;
rc = pthread_mutex_lock(&Mutex);
printf("I am Producer and I am locked\n");
if (rc != 0) {  
    printf("ERROR: return code from pthread_mutex_lock() is %d\n", rc);
    pthread_exit(&rc);
}
printf(" The ruler of all mutexes has passed from here and shall start 
creating random numbers\n");
for(int i=0; i < *(f_args->rand_count); i++){

    if(i==cb->capacity){
        printf(" Your producer king will now sleep\n");
        rc = pthread_cond_signal(&Condition);
        if (rc != 0) {  
            printf("ERROR: return code from pthread_cond_signal() is %d\n", 
    rc);
            pthread_exit(&rc);
        }

        rc = pthread_cond_wait(&Condition, &Mutex);
        if (rc != 0) {  
            printf("ERROR: return code from pthread_cond_wait() is %d\n", 
    rc);
            pthread_exit(&rc);
        }

    }

    my_random =rand_r(f_args->seed)%255;
    printf ( "Creating random number %d.\n", my_random);
    cb_push_back(cb, &my_random);
    if(i==0){
        fp=fopen("prod_in.txt", "w");
    }else{
        fp=fopen("prod_in.txt", "a");
    }
    fprintf(fp, "Producer %d: %d\n", f_args->ID, my_random);
    fclose(fp);
}
printf("I am going to go to signal the consumer.\n");

rc = pthread_cond_signal(&Condition);
if (rc != 0) {  
    printf("ERROR: return code from pthread_cond_signal() is %d\n", rc);
    pthread_exit(&rc);
}

rc = pthread_mutex_unlock(&Mutex);
if (rc != 0) {  
    printf("ERROR: return code from pthread_mutex_unlock() is %d\n", rc);
    pthread_exit(&rc);
}

}

void* Consumer(void* t1){
int *threadId = (int *) t1;
printf("I am Consumer and I am NOT locked\n");
rc = pthread_mutex_lock(&Mutex);
printf("I am Consumer and I am locked\n");
if (rc != 0) {  
    printf("ERROR: return code from pthread_mutex_lock() is %d\n", rc);
    pthread_exit(&rc);
}
if(cb->count == 0){
    rc = pthread_cond_wait(&Condition, &Mutex);
    if (rc != 0) {  
        printf("ERROR: return code from pthread_cond_wait() is %d\n", rc);
        pthread_exit(&rc);
    }
}
int counter = cb-> count;
for (int j=0; j<= counter; j++){
    printf("Consumer will now consume with items remaining %d.\n", (int)cb- 
 >count);


    if(j==0){
        fp=fopen("cons_out.txt", "w");

    }else{
        fp=fopen("cons_out.txt", "a");
    }
    printf("I will now write the following %d, %d inside the 
file.\n",*threadId,my_random);
    fprintf(fp, "Consumer %d: %d\n",*threadId, my_random);
    cb_pop_front(cb,&my_random);
    if(cb->count == 0){
        rc = pthread_cond_signal(&Condition);
        if (rc != 0) {  
            printf("ERROR: return code from pthread_cond_signal() is %d\n", 
rc);
            pthread_exit(&rc);
        }

        rc = pthread_cond_wait(&Condition, &Mutex);
        if (rc != 0) {  
            printf("ERROR: return code from pthread_cond_wait() is %d\n", 
rc);
            pthread_exit(&rc);
        }
    }

    fclose(fp);

}
rc = pthread_mutex_unlock(&Mutex);
if (rc != 0) {  
    printf("ERROR: return code from pthread_mutex_unlock() is %d\n", rc);
    pthread_exit(&rc);
}
}



int main(int argc, char *argv[]){
if (argc !=6){
    printf("ERROR: the program should take five arguments!\n");
    exit(-1);
}

if(atoi(argv[1])!= 1 || atoi(argv[2])!= 1){
    printf("ERROR:This program only functions for one producer and 
consumer.\n");
    exit(-1);
}
int main_seed = atoi(argv[5]);
int main_rand = atoi(argv[4]);
int buffer_size =  atoi(argv[3]);
cb=(circular_buffer*) malloc(sizeof(struct circular_buffer));
t_args=(args*)malloc(sizeof(struct args));
cb_init(cb, buffer_size, sizeof(int));
t_args->seed= &main_seed;
t_args->rand_count= &main_rand;
t_args->ID=1;
int t1=1;
pthread_t p1, c1;
printf ( "I am the ruler of all mutexes. I now shall initialise the 
mutex\n");
rc = pthread_mutex_init(&Mutex, NULL);
if (rc != 0) {
        printf("ERROR: return code from pthread_mutex_init() is %d\n", rc);
        exit(-1);
}

rc = pthread_cond_init(&Condition, NULL);
if (rc != 0) {
        printf("ERROR: return code from pthread_cond_init() is %d\n", rc);
        exit(-1);
}
rc = pthread_create(&p1, NULL, Producers, (void*)t_args); //cast σε void????
if (rc != 0) {
        printf("ERROR: return code from pthread_create() is %d\n", rc);
        exit(-1);
}

rc = pthread_create(&c1, NULL,Consumer,  &t1);
if (rc != 0) {
        printf("ERROR: return code from pthread_create() is %d\n", rc);
        exit(-1);
}

void *status;
rc = pthread_join(p1, &status);
if (rc != 0) {
    printf("ERROR: return code from pthread_join() is %d\n", rc);
    exit(-1);       
}
printf("Main(): Thread %d terminated successfully.\n", *(int *) status);

rc = pthread_join(c1, &status);
if (rc != 0) {
    printf("ERROR: return code from pthread_join() is %d\n", rc);
    exit(-1);       
}
printf("Main(): Thread %d terminated successfully.\n", *(int *) status);

rc = pthread_mutex_destroy(&Mutex);
if (rc != 0) {
    printf("ERROR: return code from pthread_mutex_destroy() is %d\n", rc);
    exit(-1);       
}

rc = pthread_cond_destroy(&Condition);
if (rc != 0) {
    printf("ERROR: return code from pthread_cond_destroy() is %d\n", rc);
    exit(-1);       
}
free(cb);
free(t_args);

return 1;


}

这是一个包含2个结构和循环缓冲区函数的头文件

#include "stdio.h" 
#include "sys/types.h"
#include "stdlib.h"
#include "string.h"



typedef struct circular_buffer
{
void *buffer;     // data buffer
void *buffer_end; // end of data buffer
size_t capacity;  // maximum number of items in the buffer
size_t count;     // number of items in the buffer
size_t sz;        // size of each item in the buffer
void *head;       // pointer to head
void *tail;       // pointer to tail
}circular_buffer;

typedef struct args
{
int ID;             //Unique ID from 1 to n 
int* seed;          //The seed used for rand_r
int* rand_count;    //The number of random generated numbers
}args;

void cb_push_back(circular_buffer *cb, const void *item);
void cb_pop_front(circular_buffer *cb, void *item);
void cb_init(circular_buffer *cb, size_t capacity, size_t sz);
void cb_free(circular_buffer *cb);

在此文件中是循环缓冲区函数的实现

#include "prodcons.h"

//initialize circular buffer
//capacity: maximum number of elements in the buffer
//sz: size of each element 
void cb_init(circular_buffer *cb, size_t capacity, size_t sz)
{
cb->buffer = malloc(capacity * sz);
if(cb->buffer == NULL){
    printf("Could not allocate memory..Exiting! \n");
    exit(1);
    }
    // handle error
cb->buffer_end = (char *)cb->buffer + capacity * sz;
cb->capacity = capacity;
cb->count = 0;
cb->sz = sz;
cb->head = cb->buffer;
cb->tail = cb->buffer;
}

//destroy circular buffer
void cb_free(circular_buffer *cb)
{
free(cb->buffer);
// clear out other fields too, just to be safe
}

//add item to circular buffer
void cb_push_back(circular_buffer *cb, const void *item)
{
if(cb->count == cb->capacity)
    {
        printf("Access violation. Buffer is full\n");
        exit(1);
    }
memcpy(cb->head, item, cb->sz);
cb->head = (char*)cb->head + cb->sz;
if(cb->head == cb->buffer_end)
    cb->head = cb->buffer;
cb->count++;
}

//remove first item from circular item
void cb_pop_front(circular_buffer *cb, void *item)
{
if(cb->count == 0)
    {
        printf("Access violation. Buffer is empy\n");
        exit(1);
}
memcpy(item, cb->tail, cb->sz);
cb->tail = (char*)cb->tail + cb->sz;
if(cb->tail == cb->buffer_end)
    cb->tail = cb->buffer;
cb->count--;
}

0 个答案:

没有答案