在一个结构内的结构内strdup一个char*,导致valgrind中的丢失

在一个结构内的结构内strdup一个char*,导致valgrind中的丢失,c,C,我目前正在学习C语言,并试图用程序调试一个问题 我已经将代码片段放入了一个单独的测试程序中,并成功地复制了错误,但我一辈子都看不出哪里出了问题。我想我很可能在某个地方把指针弄坏了,但不确定在哪里 下面是我的代码: typedef int BOOL; #define TRUE 1 #define FALSE 0 typedef struct CallLogSearchDataStruct { char * target; float duration; struct Ca

我目前正在学习C语言,并试图用程序调试一个问题

我已经将代码片段放入了一个单独的测试程序中,并成功地复制了错误,但我一辈子都看不出哪里出了问题。我想我很可能在某个地方把指针弄坏了,但不确定在哪里

下面是我的代码:

typedef int BOOL;
#define TRUE 1
#define FALSE 0

typedef struct CallLogSearchDataStruct
{
    char * target;
    float duration;
    struct CallLogSearchOutboundStruct * outboundLegs;
} callLogSearchDataStruct;

typedef struct CallLogSearchOutboundStruct
{
    char * target;
    float duration;
    BOOL allowOverwrite;
    struct CallLogSearchOutboundStruct *nextLeg;
} callLogSearchOutboundStruct;

callLogSearchOutboundStruct *insertOutboundLegtoList(callLogSearchOutboundStruct ** outboundLeg, char * target, float duration, BOOL overwriteFirstoutboundLegs);
void freeCallLogSearchDataStruct(callLogSearchDataStruct *callLogSearchData, int count);
void clearOutboundLinkedList(callLogSearchOutboundStruct **outboundLeg);
/*
 * 
 */
int main(int argc, char** argv) {

    int i = 0;
    int count = 10;
    callLogSearchOutboundStruct * outboundCallLegStartPtr = NULL;
    callLogSearchDataStruct * callLogSearchData = NULL;
    callLogSearchData = calloc(count, sizeof(callLogSearchDataStruct));

    for (i = 0; i < 10; i++)
    {   
    asprintf(&callLogSearchData[i].target, "Target %i", i);
    callLogSearchData[i].duration = i * 10;

    callLogSearchData[i].outboundLegs = malloc(sizeof(callLogSearchOutboundStruct));
    callLogSearchData[i].outboundLegs->target = NULL;
    callLogSearchData[i].outboundLegs->nextLeg = NULL;

    outboundCallLegStartPtr = callLogSearchData[i].outboundLegs;
    insertOutboundLegtoList(&outboundCallLegStartPtr, "OutboundTarget", i, FALSE);
    }

    freeCallLogSearchDataStruct(callLogSearchData, count);
    free(callLogSearchData);

    return (EXIT_SUCCESS);
}

callLogSearchOutboundStruct *insertOutboundLegtoList(callLogSearchOutboundStruct ** outboundLeg, char * target, float duration, BOOL overwriteFirstoutboundLegs)
{
    if (target == NULL)
    {
    return *outboundLeg;
    }

    if (!*outboundLeg)
    {
    callLogSearchOutboundStruct *newOutboundLeg = NULL;
    newOutboundLeg = malloc(sizeof(*newOutboundLeg));

    newOutboundLeg->nextLeg = NULL;
    newOutboundLeg->target = strdup(target);
    newOutboundLeg->duration = duration;
    newOutboundLeg->allowOverwrite = FALSE;
    *outboundLeg = newOutboundLeg;
    return newOutboundLeg;
    }
    if (overwriteFirstoutboundLegs == TRUE)
    {
    callLogSearchOutboundStruct * currentLeg = *outboundLeg;
    callLogSearchOutboundStruct * temp;

    free(currentLeg->target);
    currentLeg->target = strdup(target);
    currentLeg->duration = duration;
    currentLeg->allowOverwrite = FALSE;
    temp = currentLeg->nextLeg;
    while (temp)
    {
        temp->allowOverwrite = TRUE;
        temp = temp->nextLeg;
    }
    return currentLeg;
    }
    else
    {
    callLogSearchOutboundStruct **ptr = outboundLeg;
    callLogSearchOutboundStruct *currentLeg = *outboundLeg;

    if (currentLeg->target == NULL)
    {
        //This strdup is causing the loss record
        currentLeg->target = strdup(target);
        currentLeg->duration = duration;
        currentLeg->allowOverwrite = FALSE;
        *ptr = currentLeg;
        return currentLeg;
    }
    else
    {
        while (currentLeg && currentLeg->allowOverwrite == FALSE)
        {
        ptr = &currentLeg->nextLeg;
        currentLeg = currentLeg->nextLeg;
        }
        if (currentLeg)
        {
        currentLeg->target = strdup(target);
        currentLeg->duration = duration;
        currentLeg->allowOverwrite = FALSE;
        *ptr = currentLeg;
        return currentLeg;
        }
        else
        {
        currentLeg = malloc(sizeof(*currentLeg));
        currentLeg->nextLeg = NULL;
        currentLeg->target = strdup(target);
        currentLeg->allowOverwrite = FALSE;
        currentLeg->duration = duration;
        *ptr = currentLeg;
        }
    }
    return currentLeg;
    }
}

void freeCallLogSearchDataStruct(callLogSearchDataStruct *callLogSearchData, int count)
{
    int i = 0;
    for (i = 0; i < count; i++)
    {
    if (callLogSearchData[i].outboundLegs != NULL)
    {
        clearOutboundLinkedList(&callLogSearchData[i].outboundLegs);
        free(callLogSearchData[i].outboundLegs);
    }
    free(callLogSearchData[i].target);
    }
}

void clearOutboundLinkedList(callLogSearchOutboundStruct **outboundLeg)
{
    callLogSearchOutboundStruct *currentStruct = *outboundLeg;
    callLogSearchOutboundStruct *temp;

    while (currentStruct->nextLeg != NULL)
    {
        temp = currentStruct;
        currentStruct = currentStruct->nextLeg;
        free(temp->target);
        free(temp);
    }
}

正如您可以从代码中的注释中看到的,我检查currentLeg->target是否为NULL,如果为NULL,我在这个变量中添加了一个char*,但是Valgrind报告说这个strdup丢失了,但我看不出是怎么做的。由于计数器的原因,我只能给它写一次,我正在释放结构,所以不确定要去哪里看

我想我发现了您的问题,它就在这个代码示例中:

`
    if (currentLeg)
       {
           currentLeg->target = strdup(target);
           currentLeg->duration = duration;
           currentLeg->allowOverwrite = FALSE;
           *ptr = currentLeg;
           return currentLeg;
       }
`
事实上,在这种情况下,currentLeg已经将其目标链接到duuped char*数组,最好检查
currentLeg->target!=空,然后释放它:

`
    if (currentLeg)
       {
           if (currentLeg->target != NULL)
              free(currentLeg->target);
           currentLeg->target = strdup(target);
           currentLeg->duration = duration;
           currentLeg->allowOverwrite = FALSE;
           *ptr = currentLeg;
           return currentLeg;
       }
`
编辑:我找到并修补了您的错误:

改变

`
      if (callLogSearchData[i].outboundLegs != NULL)
        {
          clearOutboundLinkedList(&callLogSearchData[i].outboundLegs);
          free(callLogSearchData[i].outboundLegs);
        }
` 

`
      if (callLogSearchData[i].outboundLegs != NULL)
        {
          clearOutboundLinkedList(&callLogSearchData[i].outboundLegs);
        }
` 
并将
while(currentStruct->nextLeg!=NULL)
更改为
while(currentStruct!=NULL)
事实上,链接列表的en从未正确释放
(顺便说一句,很抱歉我的英语不好)

读的太多了!!。。。请尽量使它更简洁,这是考虑周到的。我已经指出了问题所在,我正在向您展示我在哪里释放结构,在我看来,您需要看到我在哪里分配和释放结构,以便能够提供帮助我没有遵循所有的逻辑,但是
while(currentStruct->nextLeg!=NULL)
在你的上一个函数中,它看起来很可疑-它永远不会释放列表中的最后一个节点。从某种意义上说,谢谢你的权利,这会给我带来另一个问题,尽管我认为这部分代码目前实际上没有被使用。无论如何,我已经添加了它并重建了它,但是我仍然在上面的if语句中从Valgrind得到了相同的错误。这正常吗?你从来没有进入
while(currentStruct->nextLeg!=NULL)
?谢谢你是对的,循环是问题所在,我保持了while循环不变,但是在循环之后我释放了(currentStruct)然后Valgrind说在我的头脑中没有错误,这是过度的解决方案。。;很高兴你找到了!
`
      if (callLogSearchData[i].outboundLegs != NULL)
        {
          clearOutboundLinkedList(&callLogSearchData[i].outboundLegs);
        }
`