使用getline函数的Valgrind报告内存丢失

问题描述 投票:0回答:1

我正在用C语言编写一个grep程序。我在while循环内使用getline()从流(文件或标准输入)中获取所有行。这些行存储在我定义的名为lineInText的结构内的char * lineText缓冲区中。不幸的是,即使我在循环结束时释放了此char * lineText,我仍然收到valgrind报告,说使用getline()会导致内存丢失。我究竟做错了什么?代码:线的结构及其相关功能:

typedef struct lineInText
{
    char *lineText;
    int indexOfLine;
    int numOfBytesFromStartToHere;
    bool isMatchInLine;
    bool isMatchInLineFromA;
} lineInText;


void initializeCurrentLine(lineInText *currentLine)
{
    currentLine->lineText = NULL;
    currentLine->numOfBytesFromStartToHere=0;
    currentLine->isMatchInLineFromA = false;
    currentLine->isMatchInLine = false;
    currentLine->indexOfLine = 0;
}

void FillLineStruct(lineInText *currentLine, int lineIndex, int numOfBytes) {
    currentLine->indexOfLine = lineIndex;
    currentLine->isMatchInLine = false;
    currentLine ->isMatchInLineFromA = false;
    currentLine->numOfBytesFromStartToHere = numOfBytes;
}

void freeLine(lineInText **line)
{
    free((*line)->lineText);
    free(*line);
}

main()和调用getline()的函数:

void receiveAndExecute(parsedCommandStruct *parsedCommand, FILE **stream)
{
    ssize_t lineSize = ZERO;
    lineInText *currentLine = NULL;
    int lineIndex = 1, counterForC = 0, linesAfterMatchCounter = 0, sumOfBytes = 0;
    currentLine = (lineInText *) malloc(sizeof(lineInText));
    initializeCurrentLine(currentLine);

    while (1)
    {
        readLine(stream, &lineSize, currentLine, lineIndex);
        FillLineStruct(currentLine, lineIndex, sumOfBytes);
        sumOfBytes = (int)lineSize + sumOfBytes;
        lineIndex++;
        if(lineSize<0)
            break;
        reportLineMatch(currentLine, *parsedCommand, &linesAfterMatchCounter);
        printLineToOutput(currentLine, parsedCommand, &counterForC, false);
    }
    printLineToOutput(currentLine, parsedCommand, &counterForC, true);
    freeLine(&currentLine);
}

int main(int argc, char* argv[])
{
    parsedCommandStruct *parsedCommand = NULL;
    FILE *filePtr = NULL;
    bool useFile = false;
    useFile = isUsingFile(argc, argv);
    createAndFillCommand(argc, argv, &parsedCommand);

    if (useFile)
    {
        filePtr = openFile(argv[argc-1]);
        receiveAndExecute(parsedCommand, &filePtr);
        fclose(filePtr);
    }
    else
    {
        receiveAndExecute(parsedCommand, &stdin);
    }
    freeParsedCommandStruct(parsedCommand);
    free(parsedCommand);
    return 0;
}

void readLine(FILE **stream, ssize_t *getLineResult, lineInText *currentLine,  int lineIndex) {
    ssize_t lineSize = ZERO;
    size_t lineBufSize = ZERO;
    lineSize = getline(&(currentLine->lineText), &lineBufSize, *stream);
    *getLineResult = lineSize;
}

valgrind报告:

valgrind --quiet --leak-check=yes ./my_grep bla bla | diff bla -==1878== 120 bytes in 1 blocks are definitely lost in loss record 1 of 1
==1878==    at 0x402C17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==1878==    by 0x40A9FD7: getdelim (iogetdelim.c:62)
==1878==    by 0x40A6EB1: getline (getline.c:32)
==1878==    by 0x8048E79: readLine (in /home/user/Downloads/my_grep/my_grep)
==1878==    by 0x80493EF: receiveAndExecute (in /home/user/Downloads/my_grep/my_grep)
==1878==    by 0x804952A: main (in /home/user/Downloads/my_grep/my_grep)
==1878==

预先感谢

c memory-leaks valgrind getline
1个回答
0
投票

当您调用getline时,lineBufSize的值为0。这意味着该函数认为缓冲区的长度为0个字节。这对于第一次迭代是可以的,但在后续迭代中会导致抛出存储在currentLine->lineText中的现有指针,从而导致内存泄漏。

您需要在结构中添加一个字段,以跟踪缓冲区的当前大小并将其传递给getline

typedef struct lineInText
{
    char *lineText;
    int lineTextLen;    // keep track of the size of lineText
    int indexOfLine;
    int numOfBytesFromStartToHere;
    bool isMatchInLine;
    bool isMatchInLineFromA;
} lineInText;

void initializeCurrentLine(lineInText *currentLine)
{
    currentLine->lineText = NULL;
    currentLine->lineTextLen = 0;   // initialize buffer length to 0
    currentLine->numOfBytesFromStartToHere=0;
    currentLine->isMatchInLineFromA = false;
    currentLine->isMatchInLine = false;
    currentLine->indexOfLine = 0;
}

void readLine(FILE **stream, ssize_t *getLineResult, lineInText *currentLine,  int lineIndex) {
    ssize_t lineSize = ZERO;
    lineSize = getline(&(currentLine->lineText), &(currentLine->lineTextLen), *stream);
    *getLineResult = lineSize;
}
© www.soinside.com 2019 - 2024. All rights reserved.