堆内存指针从结构内的指针字段中丢失

Posted

技术标签:

【中文标题】堆内存指针从结构内的指针字段中丢失【英文标题】:Heap memory pointer lost from pointer field inside a structure 【发布时间】:2019-07-01 08:21:57 【问题描述】:

我正在尝试使用 POSIX 线程库在 C 中实现线程池。在初始化线程池的函数中,为 thpool 和字段 jobqueue 执行动态内存分配,但是当我尝试从另一个函数访问 jobqueue 字段时,指针值为 空。这是我的代码:

threadpool.h

#include <pthread.h>

typedef void *(*funcptr) (void *);

typedef enum JOBSTATUS

    COMPLETED,
    RUNNING,
    PENDING
 jobstatus;

typedef struct _job

    funcptr f;
    void *args;
 job;

typedef struct _thpool

    job *jobqueue;
    int jobquesize;
    int jobtail;
    int jobhead;
    int occupiedjobs;

    pthread_t *threadqueue;
    int nofthreads;
    int threadsOccupied;
    pthread_mutex_t mtx;
    pthread_cond_t q_notempty;
    pthread_cond_t q_empty;
 thpool;

thpool *createWorkers(int numofthreads, int nofjobs);

threadpool.c

#include "threadpool.h"
#include <stdlib.h>
#include <stdio.h>

void *primetest(void *args)

    int *k = (int *)args;
    int i, counter;
    for (i = 0; i <= *k; i++)
    
        if (*k % i == 0)
            counter++;
    
    return counter >= 3 ? (void *)0 : (void *)1;


void *dothreadWork(void *args)

    thpool *thp = (thpool *)args;
    funcptr f;
    void *arg;
    while (1)
    
        pthread_mutex_lock(&(thp->mtx));
        while (thp->occupiedjobs == 0 /*&& thp->jobtail==thp->jobhead */ )
        
            pthread_cond_wait(&thp->q_notempty, &thp->mtx);
        
        f = thp->jobqueue[thp->jobhead].f;
        arg = thp->jobqueue[thp->jobhead].args;
        --thp->occupiedjobs;
        //if(thp->jobquesize==0)
        pthread_mutex_unlock(&(thp->mtx));
        f(arg);
    


thpool *createWorkers(int numofthreads, int nofjobs)

    int i;
    thpool *thp = (thpool *)malloc(sizeof(thpool));
    if (thp == NULL)
    
        return NULL;
    
    thp->jobqueue = (job *)malloc(sizeof(job) * nofjobs);
    if (thp->jobqueue = NULL)
    
        free(thp);
        return NULL;
    
    thp->threadqueue = (pthread_t *)malloc(sizeof(pthread_t) * numofthreads);
    if (thp->threadqueue == NULL)
    
        free(thp->jobqueue);
        free(thp);
        return NULL;
    
    pthread_mutex_init(&thp->mtx, 0);
    pthread_cond_init(&thp->q_notempty, NULL);
    pthread_cond_init(&thp->q_empty, NULL);
    thp->jobquesize = nofjobs;
    thp->jobtail = thp->jobhead = 0;
    thp->occupiedjobs = 0;
    thp->threadsOccupied = 0;
    thp->nofthreads = numofthreads;
    for (i = 0; i < numofthreads; i++)
    
        if (pthread_create(&(thp->threadqueue[i]), NULL, dothreadWork, thp) > 0)
        
            return NULL;
        
    
    return thp;

void jobqueuepush(thpool **thp, funcptr f, void *args)

    printf("Jobqueue Push!");
    pthread_mutex_lock(&((*thp)->mtx));
    if ((*thp)->jobquesize == (*thp)->occupiedjobs)
    
        pthread_mutex_unlock(&((*thp)->mtx));
        return;
    
    if ((*thp)->jobqueue == NULL)   // The problem is here
    
        pthread_mutex_unlock(&((*thp)->mtx));
        printf("Problem in memory allocation\n");
        return;
    
    //(*thp)->jobqueue[(*thp)->jobtail].f = f;
    //(*thp)->jobqueue[(*thp)->jobtail].args = args;
    //++(*thp)->occupiedjobs;
    (*thp)->jobtail = ((*thp)->jobtail + 1) % ((*thp)->jobquesize);
    if ((*thp)->occupiedjobs == 1)
        pthread_cond_signal(&((*thp)->q_notempty));
    pthread_mutex_unlock(&((*thp)->mtx));



int main(int argc, void *argv[])

    thpool *p = createWorkers(4, 2);

    if (p != NULL)
    
        int k = 4;
        jobqueuepush(&p, primetest, &k);
    
    return (EXIT_SUCCESS);

我的问题是,为什么即使我们在堆中动态分配内存,对于 struct thpooljobqueue 字段的分配指针似乎也不会保持活动状态,尽管对于 从函数 createWorkers 返回的 thpool 我们还有吗?我肯定想念这里的东西。

【问题讨论】:

请尝试创建Minimal, Complete, and Verifiable Example 向我们展示。请learn how to debug your programs。如果您在测试之间不编写大部分代码,则调试会容易得多。在只写了一小段代码之后,更频繁地进行测试。 你肯定会错过缩进。 remain alive 你是怎么诊断出来的?你是什​​么意思?我喜欢这个设计,但还有一些工作要做。基本上,这只是单个生产者的消费者-生产者问题。我相信当 //(*thp)-&gt;jobqueue[(*thp)-&gt;jobtail].f = f; 被注释掉时,你会在工作线程中调用 null。 createWorkers 函数返回时在 main 函数内部打印了指针,它与 createWorkers 函数内部分配的指针相同。我想为进程分配的堆仍然存在,直到进程结束,对吗?我也不想在这里使用全局变量来完成我的工作。 if (thp-&gt;jobqueue = NULL) 是问题所在。 【参考方案1】:

if (thp-&gt;jobqueue = NULL) 是问题所在。 ——伊恩·雅培

【讨论】:

以上是关于堆内存指针从结构内的指针字段中丢失的主要内容,如果未能解决你的问题,请参考以下文章

C 语言结构体 ( 结构体 数组 作为函数参数 | 数组 在 堆内存创建 )

智能指针

智能指针--转

C 语言内存四区原理 ( 栈内存与堆内存对比示例 | 函数返回的堆内存指针 | 函数返回的栈内存指针 )

数据结构知识基础之指针

如何具体分配一大块堆内存中的各个部分如何指针转化为地址如何求指针间地址偏移量(谈谈最近遇到的一个坑爹的接口需求)