Я не могу использовать free() для указателя символа, возвращаемого из функции

#c #memory

#c #память

Вопрос:

Я не могу очистить str переменную, выделенную в ft_itoa_base() функции. Ошибка pointer being freed was not allocated .

 void            work_ptr_accuracy(t_args *args, char **return_str, 
        va_list *arg)
{
    int                     size_accuracy;
    char                    *str_tmp;
    char                    *str;
    unsigned long long int  n;

    str_tmp = NULL;
    str = NULL;
    if (args->accuracy != -1)
    {
        size_accuracy = args->accuracy;
        n = va_arg(*arg, unsigned long long int);
        str = ft_itoa_base(n, 16, LOWERCASE);
        *return_str = ft_substr(str, 0, size_accuracy);
        free(str);
        str_tmp = ft_strjoin("0x", *return_str);
        free(*return_str);
        *return_str = str_tmp;
    }
}
 

это ft_itoa_base()

 char        *ft_itoa_base(unsigned long long int value, 
        unsigned long long int base, int regist)
{
    int                     len;
    unsigned long long int  digit;
    char                    *return_str;
    char                    *base_tmp;

    base_tmp = get_register(regist);
    if (value == 0)
        return ("0");
    len = 0;
    digit = value;
    ft_baselen(digit, base, amp;len);  
    if (!(return_str = (char *)malloc(sizeof(char) * (len   1))))
        return (NULL);
    return_str[len] = '';
    while (digit)
    {
        return_str[--len] = base_tmp[digit % base];
        digit /= base;
    }
    if (value < 0 amp;amp; base == 10)
        return_str[0] = '-';
    return (return_str);
}
 

это мой ft_substr()

 /*
** Function:        char *ft_substr
**
** Description:     Allocates (with malloc(3)) and returns a substring
** from the string ’s’.
** The substring begins at index ’start’ and is of
** maximum size ’len’.
*/

char    *ft_substr(const char *s, unsigned int start, size_t len)
{
    unsigned int    i;
    unsigned int    j;
    char            *str;

    i = 0;
    j = 0;
    if (!s)
        return (NULL);
    if (start >= ft_strlen(s))
    {
        if (!(str = (char *)malloc(1)))
            return (NULL);
        str[0] = '';
        return (str);
    }
    while (s[i] != s[start])
        i  ;
    if (!(str = (char *)malloc((len * sizeof(char))   1)))
        return (NULL);
    while (j < len amp;amp; s[i])
        str[j  ] = s[i  ];
    str[j] = '';
    return (str);
}
 

Комментарии:

1. Я понятия не имею, что ft_iota_base это значит, но вы читали документы, чтобы узнать, нужно ли их использовать free ? Основываясь на этой ошибке, я предполагаю, что вам нужно очистить ее каким-то другим способом.

2. Итак … Не делайте этого, хотя большинство / многие функции, которые возвращают указатель на что-либо, делают это с помощью malloc , это не обязательно. Некоторые функции возвращают указатель на статическую / глобальную переменную [которую вы не можете освободить — как вы выяснили]. Пример: localtime возвращает указатель на статическую / глобальную область. Если [и я повторяю: если ] значение выделено, то единственным способом получить эту ошибку будет некоторая форма повреждения кучи, которая, в данном случае, должна быть выполнена ft_substr . Поскольку вы не опубликовали исходный код ft_substr , я предполагаю, что это стандартная функция библиотеки. Если нет, опубликуйте все ft_* функции.

3. Основываясь на том, что нашел «Swift — TL; DR» :-), возможно, вам следует сделать (например) if (value == 0) return NULL;

4. @CraigEstey Я думаю, идея заключалась в том, что ft_itoa_base никогда не следует возвращать нулевой указатель, освобождение одного было бы безопасным, но использование одного не было бы, и целое число всегда преобразуется в строковое представление. Найденный код, возможно, изменен для подачи иска с любым основанием вплоть до «Z»: P

5. @Swift-FridayPie Да, я собирался добавить этот пункт в свой предыдущий комментарий, но для этого не хватило места. Прежде чем я смог добавить второй комментарий, появился ваш ответ, и пример кода охватил этот момент, поэтому [с решаемой проблемой] я не видел необходимости повторять одно и то же.

Ответ №1:

Плохой дизайн ft_itoa_base . return ("0") возвращает указатель на статически выделенный массив, состоящий из двух символов (‘0’ и »). Это невозможно free изменить.

Сравните с этой реализацией lwang <marvin@42.fr>

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

int     ft_abs(int nb)
{
    if (nb < 0)
        nb = -nb;
    return (nb);
}

char    *ft_itoa_base(int value, int base)
{
    char    *str;
    int     size;
    char    *tab;
    int     flag;
    int     tmp;
    flag = 0;
    size = 0;
    tab = "0123456789ABCDEF";
    if (base < 2 || base > 16)
        return (0);
    if (value < 0 amp;amp; base == 10)
        flag = 1;
    tmp = value;
    while (tmp /= base)
        size  ;
    size = size   flag   1;
    str = (char *)malloc(sizeof(char) * size    1);
    str[size] = '';
    if (flag == 1)
        str[0] = '-';
    while (size > flag)
    {
        str[size - 1] = tab[ft_abs(value % base)];
        size--;
        value /=base;
    }
    return (str);
}