在malloc()调用之后获取中止陷阱6

时间:2015-02-01 02:41:09

标签: c malloc abort

我是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);

工作正常。这似乎没有动态。

不确定我做错了什么。任何帮助表示赞赏。

2 个答案:

答案 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()之后进行检查,以确保它们成功。