2015-02-01 8 views
0

Я новичок в C из java и немного беспокоюсь по управлению памятью. У меня есть эта функция, целью которой является чтение x через y строк файла. Я пытаюсь написать функцию так, чтобы она могла обрабатывать любую строку размера в файле. Вот функция:Получение прерывания ловушки 6 после вызова malloc()

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, так что я могу проверить, что это растет ' должным образом. Этот размер увеличится, когда программа будет завершена. В тестовом файле, который я использую для чтения, в настоящее время есть 2 строки. Первая строка файла имеет 15 символов. Во второй строке около 90 или около того.

Когда я запускаю эту программу, я получаю ошибку Abort trap 6. После ввода некоторых отладочных операторов печати я вижу, что он выдает эту ошибку при вызове strcpy прямо под комментарием ERROR HERE в моем коде, но только для строки 2, а не для строки 1. Строка 1 также больше, чем буфер, но десятая или так что размер линии 2. Если изменить эту строку:

lineArray[index] = malloc(len * sizeof(char)); 

к:

lineArray[index] = malloc(len * sizeof(char) * 1000); 

Он работает отлично. Это просто не кажется динамичным.

Не уверен, что я делаю неправильно. Любая помощь приветствуется.

+0

Одной из потенциальных проблем является инструкция 'realloc (temp, BUFFER_SIZE);'. 'realloc' вернет новый указатель, и старое значение' temp' больше не будет считаться действительным. Простое исправление было бы присвоить возвращаемое значение 'realloc'' temp'. –

+0

Кроме того, строка '* temp = * (char *) malloc (sizeof (char) * BUFFER_SIZE);' будет захватывать случайное значение символа из неинициализированной памяти. –

+0

Drew, я изменил строку 'realloc' на' temp = realloc ... 'и это не исправило проблему :( Как мне решить проблему, возникшую во втором комментарии? – A2345sooted

ответ

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 
+0

относительно того, что часть конечного номера строки больше номера стартовой строки, я обработал это ранее в программе с помощью аргументированных аргументов; однако, вероятно, неплохо было бы это слышать и для переносимости. – A2345sooted

+0

это похоже на большое решение. Моя оригинальная функция казалась намного легче читать, с одним прыжком вверх. y идеи, почему у меня нет работы? – A2345sooted

0

Эта строка кода может быть хлопотно:

strcat (temp, buffer); 

На момент она выполняет, temp был malloc ред, но не инициализируется.

Там действительно должны быть проверки после каждого malloc(), чтобы убедиться, что они преуспели.

 Смежные вопросы

  • Нет связанных вопросов^_^