2013-03-31 3 views
3

Это проект для школы. Я закодировал функцию под названием file_to_array_d, которая помещает все символы в один массив, поэтому с файлом можно легко манипулировать.c - glibc/realloc/invalid pointer

Программа выполняет некоторые работы с файлом в соответствии с тем, что было прочитано от пользователя. В настоящее время только опция «V» и «R» должна работать. «V» выводит содержимое файла.

Все работает нормально при первом запуске основной петли (функция loop в main()). Однако на втором запуске я получаю ошибку glibc.

*** glibc detected *** ./a.out: realloc(): invalid pointer: 0x00007f01ad4397f8 *** 
======= Backtrace: ========= 
/lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7f01ad0ffb96] 
/lib/x86_64-linux-gnu/libc.so.6(realloc+0x2de)[0x7f01ad10495e] 
./a.out[0x400ec9] 
./a.out[0x400d3d] 
./a.out[0x4009b1] 
./a.out[0x40090c] 
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7f01ad0a276d] 
./a.out[0x400819] 
======= Memory map: ======== 
00400000-00402000 r-xp 00000000 08:05 3543576       /home/hork/Dropbox/FIIT/PPR/projekt/a.out 
00601000-00602000 r--p 00001000 08:05 3543576       /home/hork/Dropbox/FIIT/PPR/projekt/a.out 
00602000-00603000 rw-p 00002000 08:05 3543576       /home/hork/Dropbox/FIIT/PPR/projekt/a.out 
01318000-01339000 rw-p 00000000 00:00 0         [heap] 
7f01ace6b000-7f01ace80000 r-xp 00000000 08:05 4722212     /lib/x86_64-linux-gnu/libgcc_s.so.1 
7f01ace80000-7f01ad07f000 ---p 00015000 08:05 4722212     /lib/x86_64-linux-gnu/libgcc_s.so.1 
7f01ad07f000-7f01ad080000 r--p 00014000 08:05 4722212     /lib/x86_64-linux-gnu/libgcc_s.so.1 
7f01ad080000-7f01ad081000 rw-p 00015000 08:05 4722212     /lib/x86_64-linux-gnu/libgcc_s.so.1 
7f01ad081000-7f01ad236000 r-xp 00000000 08:05 4723475     /lib/x86_64-linux-gnu/libc-2.15.so 
7f01ad236000-7f01ad435000 ---p 001b5000 08:05 4723475     /lib/x86_64-linux-gnu/libc-2.15.so 
7f01ad435000-7f01ad439000 r--p 001b4000 08:05 4723475     /lib/x86_64-linux-gnu/libc-2.15.so 
7f01ad439000-7f01ad43b000 rw-p 001b8000 08:05 4723475     /lib/x86_64-linux-gnu/libc-2.15.so 
7f01ad43b000-7f01ad440000 rw-p 00000000 00:00 0 
7f01ad440000-7f01ad462000 r-xp 00000000 08:05 4723489     /lib/x86_64-linux-gnu/ld-2.15.so 
7f01ad63f000-7f01ad642000 rw-p 00000000 00:00 0 
7f01ad65c000-7f01ad662000 rw-p 00000000 00:00 0 
7f01ad662000-7f01ad663000 r--p 00022000 08:05 4723489     /lib/x86_64-linux-gnu/ld-2.15.so 
7f01ad663000-7f01ad665000 rw-p 00023000 08:05 4723489     /lib/x86_64-linux-gnu/ld-2.15.so 
7fffe5f17000-7fffe5f38000 rw-p 00000000 00:00 0       [stack] 
7fffe5fff000-7fffe6000000 r-xp 00000000 00:00 0       [vdso] 
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0     [vsyscall] 
Aborted (core dumped) 

Я использую Ubuntu 12.04, код компилируется с GCC

gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 

Вот полный исходный код, обратите внимание, что некоторые комментарии в словацком, но важный материал на английском языке.

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <execinfo.h> 

#define DEBUG 
#define DETAILED_DEBUG 

#define FILE_RELATIVE_PATH "ucet.txt" 

void dump(char **p, int n); 
char ** output_file(); 
char ** file_to_array_d(FILE * fd, long * rows); 
void print_trace(); 
void * xrealloc (void *ptr, size_t size); 
void fatal(char *message); 
void biggest_credit(); 


int main(int argc, char const *argv[]) 
{ 

    char argument; 

    char ** p = NULL; 
    double * suma = NULL; 

    int open = 0; 
    while((argument = getchar()) != 'K') 
    { 
     if (argument == 'V') // vypise na obrazovku obsah suboru 
     { 
      output_file(); 
      open = 1; 
     } 
     else if (argument == 'n') // aktualizuje polia 
     { 
      //number_of_records = parse_file(cena, pocet_dni); 
     } 
     else if (argument == 'l') // najlacnejsia cena 
     { 
      //calculate_lowest_price(cena, pocet_dni, number_of_records); 
     } 
     else if (argument == 'h') // histogram 
     { 
      //histogram(cena, pocet_dni, number_of_records); 
     } 
     else if (argument == 'R') // najvyssia cena za posledny rok 
     { 
      if (open) 
       biggest_credit(); 
     } 
    } 

    return 0; 
} 

char ** output_file() 
{ 
    FILE * f = fopen(FILE_RELATIVE_PATH, "r"); 
    if (f == 0) 
    { 
     printf("Neotvoreny subor\n"); 
     return 0; 
    } 

    long size = 0; 

    char ** p = NULL; 
    p = file_to_array_d(f, &size); 

    //dump(p, size); 

    printf("Size: %li\n", size); 
    int i, r = 0; 
    for (i = 0, r = 0; r < (int)size; i++, r++) 
    { 
     switch(i) 
     { 
      case 0: 
       printf("transakcia: %s\n", p[r]); 
       break; 
      case 1: 
       printf("kredit/debet: %s\n", p[r]); 
       break; 
      case 2: 
       printf("cislo uctu kam/odkial idu peniaze: %s\n", p[r]); 
       break; 
      case 3: 
       printf("suma: %s\n", p[r]); 
       break; 
      case 4: 
       printf("datum: %s\n", p[r]); 
       break; 
      case 5: 
       printf("\n"); 
       i = -1; 
       break; 
     } 
    } 

    fclose(f); 

    return p; 
} 


void biggest_credit() 
{ 
    FILE * f = fopen(FILE_RELATIVE_PATH, "r"); 
    if (f == 0) 
    { 
     return; 
    } 

    long size = 0; 

    char ** p = file_to_array_d(f, &size); 

    double max = 0; 
    int max_index; 
    int i; 

    // suma je 4. riadok, takze index 3 je prva suma 
    for (i = 3; i < size; i += 6) 
    { 
     if ( (double)atof(p[i]) > max && atoi(p[i-2]) == 1) 
     { 
      max = (double)atof(p[i]); 
      max_index = i; 
     } 
    } 

    if (max) 
    { 
     printf("%s\n", p[max_index]); 
    } 
} 


/* 
* Parameters: 
*  FILE * - pointer to the file handle 
*  long * - pointer to adress, where the number of rows is written 
* 
* Returs: 
*  char * - pointer to the start of array containing file 
* 
* Info: 
*  
*/ 
char ** file_to_array_d(FILE * fd, long * rows) 
{ 

    char c;     // current char being read from file 
    int current_row = 0; // starting from first row 
    int current_pos = 0; 


    // whole file will be stored in p[][] 
    // allocate first row 
    #ifdef DEBUG 
       printf("calling (char**) malloc(%i);\n", 1 * (int)sizeof(char *)); 
    #endif 
    char **p = (char **) malloc(1 * sizeof(char *)); 


    // until EOF is reached 
    for(current_pos = 0; ; current_pos++) 
    { 

     if (EOF == fscanf(fd, "%c", &c)) 
     { 
      if (p[current_row] == 0) 
      { 
       // un-allocate space 
       p = (char**) xrealloc(p, ((current_row) * sizeof(char *))); 
      } 

      break; 
     } 

     #ifdef DETAILED_DEBUG 
      printf("row: %2i pos: %2i\n",current_row, current_pos); 
      printf(" read char: '%c'\n\n", c); 
     #endif 

     // if char was read and it is not EOF 
     // allocate new space for char 
     #ifdef DEBUG 
      printf("calling (char*) xrealloc(p[%i ], %i);\n",current_row, current_pos+1); 
     #endif 

     p[current_row] = (char*) xrealloc(p[current_row], current_pos+1); 

     if (c != '\n') 
     { 
      // place read char there 
      p[current_row][current_pos] = c; 
     } 
     else // if new line 
     { 

      // place end of string there 
      p[current_row][current_pos] = '\0'; 

      #ifdef DATAILED_DEBUG 
       printf("\tp[%i] = '%s' \n", current_row, p[current_row]); 
      #endif 

      // allocate and increment new row 
      current_row++; 

      #ifdef DEBUG 
       printf("calling (char**) xrealloc(p, %i);\n", (current_row + 1) * (int)sizeof(char *)); 
      #endif 
      p = (char**) xrealloc(p, ((current_row + 1) * sizeof(char *)));  

      // set to -1, it will be zero in the next run of loop 
      current_pos = -1; 


      #ifdef DEBUG 
       int i; 
       for (i = 0; i < current_row; ++i) 
       { 
        printf("p[%2i] is at: %p size: %4li contains: %s\n",i, &p[i], sizeof(*p[i]) ,p[i]); 
       } 
       printf("\n"); 
      #endif 
     } 
    } 

    // if EOF is in the position: '\n EOF' 
    // right way to end file 
    if(p[current_row] == 0) 
    { 
     #ifdef DEBUG 
      printf("%s\n", "Subor je spravne ukonceny n.1 :)"); 
     #endif 
     *rows = current_row; 
    } 
    // if EOF is right behind line 
    // wrong way to end file 
    else 
    { 
     #ifdef DEBUG 
      printf("%s\n", "Subor je nespravne ukonceny !! (ale to nevadi)"); 
     #endif 
     *rows = current_row+1; 
    } 

    #ifdef DEBUG 
     printf("Number of lines: %i\n", current_row); 
    #endif 

    return p; 
} 


void * xrealloc (void *ptr, size_t size) 
{ 
    register void *value = realloc (ptr, size); 
    if (value == 0) 
     fatal ("Virtual memory exhausted"); 
    return value; 
} 

void dump(char **p, int n) 
{ 
    int i, s; 
    printf("-- DUMP --\n"); 
    for(i = 0; i < n; i++) 
    { 
     for(s = 0; p[i][s] != '\0'; s++) 
      printf("%c", p[i][s]); 
     printf("\n"); 
    } 
    printf("-- END OF DUMP --\n"); 
} 

// A function to display an error message and then exit 
void fatal(char *message) 
{ 
    char error_message[100]; 

    strcpy(error_message, "[!!] Fatal Error "); 
    strncat(error_message, message, 83); 
    perror(error_message); 
    exit(-1); 
} 

Спасибо за поддержку, это заставляет меня гайки часами.

+2

'p [current_row] = (char *) xrealloc (p [current_row], current_pos + 1);' Я не вижу, чтобы вы когда-либо инициализировали 'p [some_index]' 'NULL'. –

+0

Я не уверен, однако функция успешно выполняется в первый раз. Но когда он называется во второй раз, появляется glibc. – Horkyze

+0

То же самое для исходного 'char ** p = (char **) malloc (1 * sizeof (char *));'. – alk

ответ

2

Запустите свою программу в поле ниже Valgrind; он скажет вам точно, в чем проблема.

+4

Извините, но это было бы лучше в разделе комментариев. – alk

+0

@alk Возможно, возможно нет. Научите человека ловить рыбу и все такое. –

+0

Ребята, это не имеет значения. – Horkyze