Search code examples
cpointersgccglibcrealloc

c - glibc / realloc / invalid pointer


This is a project for school. I coded a function called file_to_array_d, which puts all characters to one array, so file can be manipulated with ease.

The program does some working with file, according to what was read from user. Currently just 'V' and 'R' option should work. 'V' prints out the content of file.

Everything works fine on the first run of main loop (loop in main() function). However on the second run I get glibc error.

*** 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)

I am using Ubuntu 12.04, code is compiled with gcc

gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3

Here is the full source code, note that some comments are in Slovak, but the important stuff is in English.

#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);
}

Thanks for support, this is driving me nuts for hours.


Solution

  • Run your program under Valgrind; it will tell you exactly what the problem is.