утечка памяти при вызове pthread_exit () - PullRequest
0 голосов
/ 09 января 2019

мне нужно создать пул потоков, он работает, но в функции do_work, которую вызывает функция pthread_create, у меня есть проблемы в свободном (утечка памяти) только при вызове pthread_exit ()

* в функции создания пула потоков я просто инициализирую структуру и вызываю функция работает *

void* do_work(void* p)
  {
   threadpool* pool = (threadpool*)p;
   work_t* work;
while(1)
{
    pthread_mutex_lock(&pool->qlock);
    if(pool->shutdown == 1)
    {

        pthread_mutex_unlock(&pool->qlock);
        //pthread_exit(EXIT_SUCCESS);// here is the free problem when deleting it all good
        return NULL;
    }
    while(!pool->qsize)
    { 
    if(pthread_cond_wait(&pool->q_not_empty,&pool->qlock)) 
         perror("pthread_cond_wait\n"); 
    if(pool->shutdown)
         break;
      } 

    //Check if the system is shutting down
    if(pool->shutdown == 1)
    {
        pthread_mutex_unlock(&pool->qlock);
        //pthread_exit(EXIT_SUCCESS);y
        return NULL;
    }

  work = pool->qhead;    //set the cur variable.

    pool->qsize--;        //decriment the size.

    if(pool->qsize == 0) {
        pool->qhead = NULL;
        pool->qtail = NULL;
    }
    else {
        pool->qhead = work->next;
    }

    if(pool->qsize == 0 && ! pool->shutdown) {
        //the q is empty again, now signal that its empty.
        pthread_cond_signal(&(pool->q_empty));
    }
    pthread_mutex_unlock(&(pool->qlock));
    (work->routine) (work->arg);   //actually do work.
    free(work);   

}
 }

1 Ответ

0 голосов
/ 09 января 2019

Шаблон выглядит как довольно стандартный пул потоков:

typedef struct {
    pthread_mutex_t   qlock;
    pthread_cond_t    q_not_empty;
    volatile work_t  *qhead;
    volatile work_t  *qtail;
    size_t            qsize; /* Not needed */
    volatile int      shutdown;
} threadpool;

Правильный отступ кода OP делает его более читабельным.

Однако реализация выглядит странно. Я бы ожидал

void *do_work(void *poolptr)
{
    threadpool *const  pool = poolptr;
    work_t            *work;

    pthread_mutex_lock(&(pool->qlock));
    while (!(pool->shutdown)) {

        if (!(pool->qhead)) {
            /* Queue empty */
            pthread_cond_wait(&(pool->q_not_empty), &(pool->qlock));
            continue;
        }

        work = pool->qhead;
        pool->qhead = work->next;
        if (!pool->qhead)
             pool->qtail = NULL;
        work->next = NULL;

        pthread_unlock(&(pool->qlock));

        work->process(work);

        pthread_lock(&(pool->qlock));

    }
    pthread_mutex_unlock(&(pool->qlock));

    return (void *)0;
}

и код, который добавляет новый рабочий элемент в очередь:

void append(threadpool *pool, work_t *work)
{
    work->next = NULL;

    pthread_mutex_lock(&(pool->qlock));
    if (pool->qtail) {
        pool->qtail->next = work;
        pool->qtail = work;
    } else {
        pool->qhead = work;
        pool->qtail = work;
    }
    pthread_cond_signal(&(pool->q_not_empty));
    pthread_mutex_unlock(&(pool->qlock));
}

Трудно сказать, где реализация OP утечка памяти. Наиболее вероятным кандидатом является член arg OP в каждом work_t, если он выделяется динамически.

Моя реализация выше передает всю work_t функции routine, которую я переименовал в process. Он также отвечает за освобождение рабочей структуры. Минимальное определение для структуры работы:

typedef struct work_t {
    struct work_t  *next;
    void          (*process)(struct work_t *);
    /* Optional other fields */
} work_t;

Другие возможные причины утечек памяти связаны с тем, что элемент qsize не везде обновляется должным образом. Потому что на самом деле это бесполезно, я просто опускаю все это.

Чем проще код, тем легче избежать ошибок.

...