我是Java的新手,在内存管理方面遇到了一些麻烦。我有这个函数,其目的是读取文件的x到y行。我正在尝试编写该函数,以便它可以处理文件中的任何大小的行。这是功能:
char** getRangeOfLinesFromFile(char* fileName, int startingLineNumber, int endingLineNumber, int BUFFER_SIZE) {
//set up an array to hold the range of lines we're going to return
//+1 because the range is inclusive
char** lineArray = malloc((endingLineNumber - startingLineNumber + 1) * sizeof(char*));
//get the file
FILE* file_ptr = fopen(fileName,"r");
//our buffer array will hold the lines as we read them
char *buffer = (char*) malloc(sizeof(char) * BUFFER_SIZE);
//this array will be used just in case a line is bigger than our buffer and we need to take multiple passes at it
char *temp = (char*) malloc(sizeof(char) * BUFFER_SIZE);
int lineCounter = 1;
while (fgets(buffer, BUFFER_SIZE, file_ptr) != NULL) {
strcat(temp, buffer);
size_t len = strlen(temp);
if (temp[len - 1] != '\n') {
realloc(temp,BUFFER_SIZE);
} else {
if (shouldKeepLine(lineCounter,startingLineNumber,endingLineNumber)) {
int index = lineCounter - startingLineNumber;
lineArray[index] = malloc(len * sizeof(char));
//ERROR HERE
strcpy(lineArray[index],temp);
}
*temp = *(char*) malloc(sizeof(char) * BUFFER_SIZE);
lineCounter++;
// we don't need to keep reading the file if we're not going to print anything else
if (lineCounter > endingLineNumber) {
break;
}
}
}
//clean up
free(buffer);
free(temp);
fclose(file_ptr);
return lineArray;
}
这就是shouldKeepLine()函数的样子:
bool shouldKeepLine(int lineNumber, int lowerBound, int upperBound) {
if (lineNumber >= lowerBound && lineNumber <= upperBound) {
return true;
}
return false;
}
在测试过程中,我使用的缓冲区大小为10,因此我可以测试它是否正常“增长”。程序完成后,此大小将增加。我用来读取的测试文件目前有两行。该文件的第一行有15个字符。第二行约有90左右。
当我运行此程序时,出现Abort trap 6错误。在放入一些调试打印语句之后,我看到它在我的代码中的ERROR HERE注释下方的strcpy调用上抛出了该错误,但仅针对第2行,而不是第1行。第1行也大于缓冲区但是第10行左右第2行的大小。如果我改变这一行:
lineArray[index] = malloc(len * sizeof(char));
为:
lineArray[index] = malloc(len * sizeof(char) * 1000);
工作正常。这似乎没有动态。
不确定我做错了什么。任何帮助表示赞赏。
答案 0 :(得分:0)
the following code should (not compiled/tested)
perform the activity you want to implement
char** getRangeOfLinesFromFile(
char* fileName,
int startingLineNumber, // note: first line in file is considered line 1, not 0
int endingLineNumber,
int BUFFER_SIZE )
{
//set up an array to hold the range of lines we're going to return
//+1 because the range is inclusive
char** lineArray = NULL;
// what about if endingLineNumber is < startingLine Number???
int lineCount = endingLineNumber - startingLineNumber + 1;
int i; // loop counter/index
// get array of pointers to point to each line that is kept
if( NULL == (lineArray = malloc( (lineCount) * sizeof(char*)) ) )
{ // then, malloc failed
perror( "malloc for array of pointers failed" );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
// *I* would use the getline()) function, so the length of the
// input line would not matter.
// however, the following code uses the passed in value BUFFER_SIZE
// (which I would have made a #define and not passed it in)
// initialize the array of pointers to char
for( i=0; i<lineCount; i++)
{
if( NULL == (lineArray[i] = malloc(BUFFER_SIZE) ) )
{ // then malloc failed
perror( "malloc for each line storage area failed" );
// free all allocated memory
// suggest using the cleanup() function, below
exit( EXIT_FAILURE );
}
// implied else, malloc successful
// (optional, but good practice)
// clear each memory allocated area to NUL bytes
memset( lineArray[i], 0x00, BUFFER_SIZE );
} // end for
// if got here, then all memory allocations are completed
//get the file
FILE* file_ptr = NULL;
if( NULL == (file_ptr = fopen(fileName,"r") ) )
{ // then, fopen failed
perror( "fopen for input file failed" );
// free all allocated memory
// suggest using the cleanup() function, below
exit( EXIT_FAILURE );
}
// implied else, fopen successful
for(i=0; i < (startingLineNumber-1); i++)
{
unsigned int inputChar;
while( (inputChar = fgetc( file_ptr )) != EOF
{
if( EOF == inputChar )
{ // then, file does not contain nearly enough lines
// free all allocated memory
// suggest using cleanup() function, below
fclose( file_ptr );
return (NULL);
}
if( '\n' == inputChar ) { break;} // end of current line
} // end while
} // end for
// if got here, then ready to read first line of interest
// NOTE: be sure there is a newline at end of input file
int bufLength = BUFFER_SIZE;
for( i=0; i<lineCount; i++ )
{
// get a line, allowing for max input buffer length
if( fgets( &lineArray[i][strlen(lineArray[i])], BUFFER_SIZE, file_ptr ) )
{ // then got (more) line, up to BUFFER_SIZE -1
if( '\n' != lineArray[i][(strlen( lineArray[i] )-1) )
{ // then more char available for this line
char *tempPtr = NULL;
if( NULL == (tempPtr = realloc( lineArray[i], (bufLength*2) ) ) )
{ // then, realloc failed
perror( "realloc to increase buffer size failed" );
// add --free all the allocations--
// suggest sub function with passed parameters
fclose( file_ptr );
exit( EXIT_FAILURE );
}
// implied else, realloc successful
// update the pointer in the array
lineArray[i] = tempPtr;
// update buffer length indication
bufLength *= 2;
i--; // so will append to same entry in array for rest of line
}
else
{ // else, got all of line
bufLength = BUFFER_SIZE; // reset
} // end if
}
else
{ // else, fgets failed
perror( "fgets for line failed" );
// add --free all allocations--
// suggest sub function with passed parameters
fclose( file_ptr );
exit( EXIT_FAILURE );
} // end if
} // end for
// if got here, then all desired lines read successfully
fclose( file_ptr );
return lineArray;
} // end function: getRangeOfLinesFromFile
remember that the caller has to free all those memory allocations
first the allocation for each line
then the allocation for the lineArray
perhaps like this:
void cleanup( char**pArray, int entryCount )
{
int i; // loop counter/index
for( i=0; i<entryCount; i++ )
{
free(pArray[i]);
}
free(pArray);
} // end function: cleanup
答案 1 :(得分:0)
这行代码可能很麻烦:
strcat (temp, buffer);
在执行时,temp
已被malloc
编辑,但尚未初始化。
确实应该在每malloc()
之后进行检查,以确保它们成功。