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

时间:2015-03-24 16:01:37

标签: c memory-management memory-leaks struct valgrind

我目前正在开发一个项目,我正在使用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 for outbound struct

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的新手,我正在学习它。

1 个答案:

答案 0 :(得分:0)

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

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

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

请记住,strdup()始终会分配调用者负责释放的内存。我看到你在函数clearOutboundLinkedList()中正确地释放了这个成员,所以它必须是outboundStruct某处超出范围或被释放而不被该函数处理。

仔细观察,然后,我看到您的main()函数调用mallocOutboundStruct()两次,在变量outboundDataStruct中保留结果指针中的一个。之后通过clearOutboundLinkedList()释放了一个,但另一个永远不会。事实上,另一个根本没有被释放,这似乎是第二次失败记录的主题。