我正在用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(¤tLine);
}
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==
预先感谢
当您调用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;
}