Errore: double free detected in tcache 2

di il
6 risposte

Errore: double free detected in tcache 2

Salve, non riesco a capire da dove arrivi questo problema dato che e la prima volta che lo incontro, non mi sembra di andare a fare free 2 volte sulla stessa variabile.

l'input utilizzato e un file di testo con dentro questo: 01234567890123456789012345678901234567890 (no newline)

il main e un semplice ciclo che richiama a get next line.

Con GDB ho appurato che il programma va in segfault nella funzione buffer_handler, alla seconda chiamata (dopo essere arrivata a fine file) i byte letti sono 0;

dovrebbe restituire NULL ma si ferma quando cerco di fare il free di stock.

Grazie in anticipo a chiunque abbia la pazienza di aiutarmi :)

(Ps. fate sapere qualora dovesse servirvi anche il file con le funzioni di appoggio)

char **trim_buffer(char *str)
{
    int i;
    char **tmp;
    i = 0;
    while (str[i] != '\0')
    {
        if (str[i] == '\n')
        {
            tmp = ft_split(str, '\n');
            return (tmp);
        }
        i++;
    }
    return (NULL);
}

static char **buffer_handler(char *buffer, int fd)
{
    char    *tmp;
    char    **trim_result;
    char    **stock;
    int     read_bytes;
    int     i;

    i = 0;
    stock = (char **)malloc(sizeof(char *) * 2);
    tmp = (char *)malloc(sizeof(char) * BUFFER_SIZE);

    if (!tmp || !stock)
        return (NULL);

    read_bytes = read(fd, tmp, BUFFER_SIZE);
    if (read_bytes == 0)
    {
        free(tmp);
        while (stock[i] != NULL)
            free(stock[i++]);
        free(stock);
        return (NULL);
    }
    trim_result = trim_buffer(tmp);
    if (trim_result)
    {
        tmp = trim_result[0];
        tmp = ft_strjoin(tmp, "\n");
        stock[1] = ft_strdup(trim_result[1]);
    }
    tmp = ft_strjoin(buffer, tmp);
    stock[0] = ft_strdup(tmp);
    free(tmp);
    return (stock);
}

char    *get_next_line(int fd)
{
    char            *stock_buffer;
    static char     *res;
    char            *next_line;
    char            **holder;

    next_line = NULL;
    stock_buffer = NULL;
    // Last control to fix the segfault with invalid fd
    if (fd < 0 || BUFFER_SIZE <= 0 || read(fd, next_line, 0) < 0)
	    return (NULL);
    if (res)
	    stock_buffer = ft_strjoin(stock_buffer, res);
    while (ft_strchr(stock_buffer, '\n') == 0)
    {
        holder = buffer_handler(stock_buffer, fd);
        if (holder == NULL && stock_buffer == NULL)
        {
            return (NULL);
        }
        else if (holder == NULL && stock_buffer[0] == '\0')
            return (NULL);
        else if (holder == NULL)
        {
            next_line = stock_buffer;
            return (next_line);
        }
        stock_buffer = ft_strdup(holder[0]);
        res = ft_strdup(holder[1]);
    }
    next_line = stock_buffer;
    return (next_line);
}

6 Risposte

  • Re: Errore: double free detected in tcache 2

    Questo ciclo

    while (stock[i] != NULL)
                free(stock[i++]);

    quando si ferma? Come controlli i ?

  • Re: Errore: double free detected in tcache 2

    Mi dava lo stesso errore comunque facendo direttamente free su: stock[0] & stock[1]

  • Re: Errore: double free detected in tcache 2

    Hai allocato due puntatori ma non hai allocato lo spazio a cui puntano i due puntatori. Manca il ciclo di allocazione.

    E comunque il ciclo while del free è evidentemente sbagliato, correggilo

  • Re: Errore: double free detected in tcache 2

    Lo spazio dentro i puntatori viene allocato nel trim_buffer che fa lo split, il free dello stock l'ho rimosso in quel punto e il problema e andato via allocando con calloc (pare che gli desse fastidio l'array non inizializzato), adesso il programma funziona, tuttavia ci sono ancora 102 byte di memoria persa.

    Valgrind:

    ==52753== HEAP SUMMARY:
    ==52753==     in use at exit: 103 bytes in 2 blocks
    ==52753==   total heap usage: 14 allocs, 12 frees, 565 bytes allocated
    ==52753== 
    ==52753== 2 bytes in 1 blocks are definitely lost in loss record 1 of 2
    ==52753==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==52753==    by 0x109343: ft_strdup (get_next_line.c:53)
    ==52753==    by 0x109856: get_next_line (get_next_line.c:206)
    ==52753==    by 0x1098F6: main (main.c:22)
    ==52753== 
    ==52753== 101 bytes in 1 blocks are definitely lost in loss record 2 of 2
    ==52753==    at 0x483DD99: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==52753==    by 0x1095D5: buffer_handler (get_next_line.c:137)
    ==52753==    by 0x1097C9: get_next_line (get_next_line.c:190)
    ==52753==    by 0x1098F6: main (main.c:22)
    ==52753== 
    ==52753== LEAK SUMMARY:
    ==52753==    definitely lost: 103 bytes in 2 blocks
    ==52753==    indirectly lost: 0 bytes in 0 blocks
    ==52753==      possibly lost: 0 bytes in 0 blocks
    ==52753==    still reachable: 0 bytes in 0 blocks
    ==52753==         suppressed: 0 bytes in 0 blocks

    Modifiche:

    static char **buffer_handler(char *buffer, int fd)
    {
        char    *tmp;
        char    **trim_result;
        char    **stock;
        int     read_bytes;
    
        tmp = (char *)calloc(sizeof(char), (BUFFER_SIZE + 1));
        if (!tmp)
            return (NULL);
        read_bytes = read(fd, tmp, BUFFER_SIZE);
        if (read_bytes == 0)
        {
            free(tmp);
            return (NULL);
        }
        trim_result = trim_buffer(tmp);
        if (trim_result != NULL)
            stock = (char **)calloc(sizeof(char *), 2);
        else
            stock = (char **)calloc(sizeof(char *), 1);
        if (!stock)
        {
            free(tmp);
            return (NULL);
        }
        if (trim_result)
        {
            tmp = trim_result[0];
            tmp = ft_strjoin(tmp, "\n");
            stock[1] = ft_strdup(trim_result[1]);
            free(trim_result[0]);
            free(trim_result[1]);
            free(trim_result);
        }
        if (buffer)
            tmp = ft_strjoin(buffer, tmp);
        stock[0] = ft_strdup(tmp);
        free(tmp);
        return (stock);
    }
    
    char    *get_next_line(int fd)
    {
        char            *stock_buffer;
        static char     *res;
        char            *next_line;
        char            **holder;
        int             i;
    
        i = 0;
        next_line = NULL;
        stock_buffer = NULL;
        // Last control to fix the segfault with invalid fd
        if (fd < 0 || BUFFER_SIZE <= 0 || read(fd, next_line, 0) < 0)
    	    return (NULL);
        if (res)
    	    stock_buffer = ft_strjoin(stock_buffer, res);
        while (ft_strchr(stock_buffer, '\n') == 0)
        {
            holder = buffer_handler(stock_buffer, fd);
            if (holder == NULL && stock_buffer == NULL)
            {
                free(stock_buffer);
                return (NULL);
            }
            else if (holder == NULL && stock_buffer[0] == '\0')
                return (NULL);
            else if (holder == NULL)
            {
                res = NULL;
                next_line = stock_buffer;
                //free(stock_buffer);
                return (next_line);
            }
            stock_buffer = ft_strdup(holder[0]);
            res = ft_strdup(holder[1]);
        }
        next_line = ft_strdup(stock_buffer);
    	free(holder[0]);
    	free(holder[1]);
        free(holder);
        free(stock_buffer);
        return (next_line);
    }
  • Re: Errore: double free detected in tcache 2

    Per provare il codice serve il main e le funzioni necessarie per compilare senza errori 

  • Re: Errore: double free detected in tcache 2

    Comunque non mi pare di vedere le free per stock[0] e stock[1] quando della memoria è allocata per questi puntatori.

Devi accedere o registrarti per scrivere nel forum
6 risposte