簡體   English   中英

為什么C不會從strtok設置的malloc'd char *中釋放內存?

[英]Why isn't C freeing memory from malloc'd char* set by strtok?

此函數將具有空格分隔值的文本文件中的值讀取到2d數組中。 當我運行它時,工作得很好 - 但通過Valgrind進行的內存泄漏檢查確認了Xcode懷疑“char * splitString”從未被釋放,這是它被稱為的兩次。 我不明白這一點,考慮到我的“char * buffer”似乎被釋放得很好。 任何幫助都非常感謝!

int** readMatrixFile(char* inFileName, int** matrix, int sizeY, int sizeX)
{
    FILE* matrixFP;
    int ii=0, jj=0, fileValid = 1;
    char *buffer, *splitString;
    const char delim[]=" \n\r";

    matrixFP = fopen(inFileName, "r");
    if(matrixFP != NULL)
    {
        /*Check if file is the same size as specified by the command line
         *assumed valid until the file is checked*/
        splitString = malloc(100*sizeof(char)); <------where allocated
        buffer = malloc(5000*sizeof(char));
        do
        {
            fgets(buffer, 5000, matrixFP);
            jj=0;
            splitString = strtok(buffer, delim);
            while(splitString != NULL)
            {
                jj++;
                splitString = strtok(NULL, delim);
            }
            if(jj!=sizeX)
            {
                fileValid = 0;
            }
            ii++;
        } while(!feof(matrixFP));
        if(ii != sizeY || buffer==NULL)
        {
            fileValid = 0;
        }

        free(splitString); <-----Appears to do nothing?
        free(buffer);

        if(fileValid) /*Files match to specified command line values*/
        {
            ii=0;
            rewind(matrixFP);
            matrix = (int**)malloc(sizeY * sizeof(int *));
            do
            {
                matrix[ii] = (int*)malloc(sizeX * sizeof(int));
                jj=0;
                do
                {
                    fscanf(matrixFP, "%d", &matrix[ii][jj]);
                    jj++;
                } while(jj<sizeX);
                ii++;
            } while(ii<sizeY && !feof(matrixFP));
        }
        else
        {
            printf("Error: File does not match size specified by the command line\n");
        }
        fclose(matrixFP);
    }
    else
    {
        perror("Error: File does not exist or is invalid");
        matrix = NULL;
    }

    return matrix;
}

和Valgrind輸出:

==14087== Memcheck, a memory error detector
==14087== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==14087== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==14087== Command: ./pmms a b 10 3 10
==14087== 
/*irrelevent program output*/ 
==14087== 
==14087== HEAP SUMMARY:
==14087==     in use at exit: 200 bytes in 2 blocks
==14087==   total heap usage: 21 allocs, 19 frees, 11,680 bytes allocated
==14087== 
==14087== 100 bytes in 1 blocks are definitely lost in loss record 1 of 2
==14087==    at 0x4A06A2E: malloc (vg_replace_malloc.c:270)
==14087==    by 0x400B55: readMatrixFile (matrix_reader.c:35)
==14087==    by 0x40095E: main (pmms.c:23)
==14087== 
==14087== 100 bytes in 1 blocks are definitely lost in loss record 2 of 2
==14087==    at 0x4A06A2E: malloc (vg_replace_malloc.c:270)
==14087==    by 0x400B55: readMatrixFile (matrix_reader.c:35)
==14087==    by 0x400982: main (pmms.c:24)
==14087== 
==14087== LEAK SUMMARY:
==14087==    definitely lost: 200 bytes in 2 blocks
==14087==    indirectly lost: 0 bytes in 0 blocks
==14087==      possibly lost: 0 bytes in 0 blocks
==14087==    still reachable: 0 bytes in 0 blocks
==14087==         suppressed: 0 bytes in 0 blocks
==14087== 
==14087== For counts of detected and suppressed errors, rerun with: -v
==14087== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 6 from 6)

您可以在此處更改splitString的值:

            splitString = strtok(NULL, delim);

和這里:

            splitString = strtok(buffer, delim);

因此它不再指向要釋放的內存塊,因此free()將不執行任何操作,因為到達此行時, splitString將為NULL ,並且free(NULL)被定義為不執行任何操作。

首先,你迭代

    while(splitString != NULL)
    {
          ...
    }

所以在循環完成后, splitStringNULL ,而free(NULL)什么都不做。

第二,一旦你分配了一個百字節的內存塊

    splitString = malloc(100*sizeof(char));   // (*)

splitString變量的下一個引用是一個賦值:

    splitString = strtok(buffer, delim);

所以,無論存儲在變量中的是什么,都會被覆蓋! splitString現在指向buffer塊,並且(*)分配的塊的地址永遠丟失。 順便說一句,這表明你從不使用那個塊,而你實際上並不需要分配它。

while(splitSring != NULL)循環中你使用strtok(3)來修改它。 在循環結束時, splitString將為NULL並且基本上您正在調用free(NULL) ,同時泄漏最初分配的內存。

這不是您問題的直接答案,只是一個可能有助於完全避免問題的建議:

使用strtok()和family時,您不需要為用於捕獲返回值的對象顯式分配內存:

char delim[] = {" \n\t"};  //or whatever delimitors you need
char *tok = NULL;

tok = strtok(stringToParse, delim);  
while(tok)
{
    //do something with tok
    ...
    //get next token:
    tok = strtok(NULL, delim);
}

而且,也沒有必要免費tok時,如圖所示。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM