结构和链表内存分配valgrind错误

Structure and Linked List memory allocation valgrind error

我目前正在做一个项目,在这个项目中我使用 valgrind 来查找内存泄漏,但我在尝试查找它们时遇到了一些麻烦。

我制作了一个小应用程序来模拟问题出在哪里,并且我已经成功地复制了我在 valgrind 中看到的错误。

下面是我的主要功能:

int main(int argc, char** argv) {


    inboundStruct * inboundDataStruct = NULL;
    outboundStruct * outboundDataStruct = NULL;
    char *outboundName = NULL;
    if (mallocInboundStruct(&inboundDataStruct, 2))
    {
        printf("Error malloc'ing inbound struct\n");
        exit(1);
    }
    int i = 0;
    for (i = 0; i < 2; i++)
    {
        inboundDataStruct[i].index = i;
        asprintf(&inboundDataStruct[i].itemName, "Item %i", i);
        mallocOutboundStruct(&inboundDataStruct[i].outboundLeg);
        if (outboundDataStruct == NULL)
        {
            outboundDataStruct = inboundDataStruct[i].outboundLeg;
        }

        asprintf(&outboundName, "Outbound Target %i", i);
        insertOutboundLeg(&outboundDataStruct, outboundName, i);
        outboundDataStruct = NULL;
        free(outboundName);
        outboundName = NULL;
    }  
    printStructure(inboundDataStruct, 2);

    clearOutboundLinkedList(&outboundDataStruct);

    freeInboundStruct(&inboundDataStruct, 2);

    return (EXIT_SUCCESS);
}

下面是我的入站结构的 malloc 函数

int mallocInboundStruct(inboundStruct **inboundDataStruct, int size)
{
    int i = 0;
    inboundStruct *tempStruct = NULL;
    tempStruct = (inboundStruct*)malloc(size * sizeof(inboundStruct));
    if (tempStruct != NULL)
    {
        for (i = 0; i < size; i++)
        {
            tempStruct[i].index = i;
            tempStruct[i].itemName = NULL;
        }
        *inboundDataStruct = tempStruct;
        return 0;
    }
    return 1;
}

下面是我的出站结构 malloc

int mallocOutboundStruct(outboundStruct **outboundDataStruct)
{
    outboundStruct *tempStruct = NULL;

    tempStruct = (outboundStruct*)malloc(sizeof(outboundStruct));
    if (tempStruct != NULL)
    {
        tempStruct->index = 0;
        tempStruct->nextLeg = NULL;
        tempStruct->outboundName = NULL;
        *outboundDataStruct = tempStruct;
        return 0;
    }
    return 1;
}

下面没有入站结构

int freeInboundStruct(inboundStruct **inboundDataStruct, int size)
{
    inboundStruct *tempStruct = *inboundDataStruct;
    int i = 0;

    for (i = 0; i < size; i++)
    {
        free(tempStruct[i].itemName);
        tempStruct[i].itemName = NULL;
    }
    free(tempStruct);
    return 0;
}

下面是出站结构的释放

int clearOutboundLinkedList(outboundStruct **outboundDataStruct)
{
    outboundStruct *currentStruct = *outboundDataStruct;
    outboundStruct *temp;

    if (currentStruct == NULL)
    {
        return 0;
    }
    while (currentStruct->nextLeg != NULL)
    {
        temp = currentStruct;
        currentStruct = currentStruct->nextLeg;
        free(temp->outboundName);
        temp->outboundName = NULL;
        free(temp);
    }
    free(currentStruct->outboundName);
    currentStruct->outboundName = NULL;
    free(currentStruct);
    currentStruct = NULL;
    return 0;
}

最后下面是将数据插入出站结构的函数

void insertOutboundLeg(outboundStruct ** outboundDataStruct, char * outboundName, int index)
{
    outboundStruct **ptr = outboundDataStruct;
    outboundStruct *currentLeg = *outboundDataStruct;

    if (currentLeg->outboundName == NULL)
    {
        currentLeg->index = index;
        //asprintf(&currentLeg->outboundName, "Item %s-%i", outboundName, index);
        currentLeg->outboundName = strdup(outboundName);
        *ptr = currentLeg;
    }
    else
    {
        while (currentLeg)
        {
            ptr = &currentLeg->nextLeg;
            currentLeg = currentLeg->nextLeg;
        }
        if (currentLeg)
        {
            if (currentLeg->outboundName != NULL)
            {
                free(currentLeg->outboundName);
                currentLeg->outboundName = NULL;
            }
            //asprintf(&currentLeg->outboundName, "Item %s-%i", outboundName, index);
            currentLeg->outboundName = strdup(outboundName);
            currentLeg->index = index;
            *ptr = currentLeg;
        }
        else
        {
            currentLeg = malloc(sizeof(*currentLeg));
            currentLeg->nextLeg = NULL;
            //asprintf(&currentLeg->outboundName, "Item: %s-%i", outboundName, index);
            currentLeg->outboundName = strdup(outboundName);
            currentLeg->index = index;
            *ptr = currentLeg;
        }
    }
}

当我通过 valgrind 运行 应用程序时,它会给我以下输出:

> ==32080== Command: ./mallocTest
> ==32080== Index: 0 Item: Item 0
>         Index: 0 Item: Outbound Target 0 Index: 0 Item: Item 1
>         Index: 1 Item: Outbound Target 1
> ==32080==
> ==32080== HEAP SUMMARY:
> ==32080==     in use at exit: 60 bytes in 4 blocks
> ==32080==   total heap usage: 13 allocs, 9 frees, 534 bytes allocated
> ==32080==
> ==32080== 36 bytes in 2 blocks are indirectly lost in loss record 1 of 2
> ==32080==    at 0x40072D5: malloc (vg_replace_malloc.c:291)
> ==32080==    by 0xB0798F: strdup (in /lib/libc-2.12.so)
> ==32080==    by 0x804869D: insertOutboundLeg (main.c:86)
> ==32080==    by 0x80485FF: main (main.c:38)
> ==32080==
> ==32080== 60 (24 direct, 36 indirect) bytes in 2 blocks are definitely lost in loss record 2 of 2
> ==32080==    at 0x40072D5: malloc (vg_replace_malloc.c:291)
> ==32080==    by 0x80488A4: mallocOutboundStruct (main.c:157)
> ==32080==    by 0x80485A3: main (main.c:31)
> ==32080==
> ==32080== LEAK SUMMARY:
> ==32080==    definitely lost: 24 bytes in 2 blocks
> ==32080==    indirectly lost: 36 bytes in 2 blocks
> ==32080==      possibly lost: 0 bytes in 0 blocks
> ==32080==    still reachable: 0 bytes in 0 blocks
> ==32080==         suppressed: 0 bytes in 0 blocks
> ==32080==
> ==32080== For counts of detected and suppressed errors, rerun with: -v
> ==32080== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 12 from 8)

我认为问题可能出在我的 insertOutboundLeg 上,但我不明白为什么。我是 C 的新手,并且正在学习它。

Valgrind 告诉您丢失的内存分配到哪里;它无法告诉您该内存在哪里无法访问。问题通常不在于分配,而在于之后如何处理分配的内存。

在您的情况下,第一个丢失记录告诉您通过调用 strdup()insertOutboundLeg() 中分配的一块内存已泄漏。我没有行号来指导我,但看起来那必须是

的几次出现之一
currentLeg->outboundName = strdup(outboundName);

请始终记住,strdup() 分配调用者负责释放的内存。我看到你在你的函数 clearOutboundLinkedList() 中正确地释放了这个成员,所以一定是 outboundStruct 某个地方超出了范围或者在没有被该函数处理的情况下被释放。

仔细观察,然后,我看到您的 main() 函数调用了 mallocOutboundStruct() 两次,并在变量 [=18] 中保留 恰好一个 结果指针=].那个后来通过 clearOutboundLinkedList() 被释放,但另一个从未被释放。事实上,另一个从未被释放根本,这似乎是第二个损失记录的主题。