2016-11-13 4 views
0

В этой функции, у меня есть утечка памятиУтечки памяти в C

static int  read_buffer(int const fd, char **buffer) 
{ 
     char buff[BUFF_SIZE + 1]; 
     int  ret; 

     ret = read(fd, buff, BUFF_SIZE); 
     if (ret > 0) 
     { 
       buff[ret] = 0; 
       if (!(*buffer = ft_strjoin(*buffer, buff))) 
         return (-1); 
     } 
     return (ret); 
} 

Я пытался сделать это и больше решения снова .. Но я получаю также утечку памяти

static int  read_buffer(int const fd, char **buffer) 
{ 
     char buff[BUFF_SIZE + 1]; 
     char *tmp; 
     int  ret; 

     ret = read(fd, buff, BUFF_SIZE); 
     tmp = *buffer; 
     if (ret > 0) 
     { 
       buff[ret] = 0; 
       if (!(*buffer = ft_strjoin(*buffer, buff))) 
         return (-1); 
       free(tmp); 
     } 
     return (ret); 
} 

Здесь является функцией ft_strjoin: (не может быть изменено)

char *ft_strjoin(char const *s1, char const *s2) 
{ 
    size_t size_s1; 
    size_t size_s2; 
    char *strjoin; 

    size_s1 = ft_strlen(s1); 
    size_s2 = ft_strlen(s2); 
    if (!(strjoin = malloc(size_s1 + size_s2 + 1))) 
     return (NULL); 
    ft_strcpy(strjoin, s1); 
    ft_strcat(strjoin, s2); 
    return (strjoin); 
} 

Как я могу это решить?
Спасибо!

+0

Не могли бы вы объяснить, что заставляет вас думать, что есть утечка памяти? Используемый инструмент также может дать вам несколько советов по этой проблеме. – kebs

+0

@kebs Я использовал valgrind, но он вернул мне это вызвало функцию ft_strjoin –

+0

Мне нравится отступ, но используйте некоторые фигурные скобки –

ответ

0

В любое время функция возвращает память malloc'd, у вас есть горячий картофель. Вы должны освободить эту память и не можете передать ее, если только вы не задокументировали, что делаете это. И вы не должны потерять (например, повторное использование) указатель перед его освобождением. Ниже я расскажу, как должен работать read_buffer(). Поскольку «длина буфера неизвестна» Я предполагаю, что это происходит из malloc и мы можем использовать realloc:

static int read_buffer(int const fd, char **buffer) 
{ 
    char local_buffer[BUFF_SIZE + 1]; 

    int bytes_read = read(fd, local_buffer, BUFF_SIZE); 

    if (bytes_read > 0) 
    { 
     local_buffer[bytes_read] = '\0'; 

     char *joined = ft_strjoin(*buffer, local_buffer); 

     if (joined != NULL) 
     { 
      *buffer = realloc(*buffer, strlen(joined) + 1); 

      if (*buffer != NULL) 
      { 
       ft_strcpy(*buffer, joined); 
      } 
      else 
      { 
       bytes_read = -1; 
      } 

      free(joined); 
     } 
     else { 
      bytes_read = -1; 
     } 
    } 

    return bytes_read; 
} 

Обратите внимание, что есть много потенциальных ловушек, которые вы должны проверить и восстанавливаться.

Если вы читаете от пользователя непосредственно, и не хотят новой строки как часть конкатенации строк, вы можете заменить эту строку:

 local_buffer[bytes_read] = '\0'; 

что-то вроде:

if (local_buffer[bytes_read - 1] == '\n') 
    { 
     local_buffer[bytes_read - 1] = '\0'; 
    } 
    else 
    { 
     local_buffer[bytes_read] = '\0'; 
    } 

Предполагая, выше новой строки исправить, вот небольшой тест программа, которую я написал:

int main() { 

    char *buffer = malloc(1); 

    *buffer = '\0'; 

    for (int i = 0; i < 3; i++) 
    { 
     (void) read_buffer(0, &buffer); 

     puts(buffer); 
    } 

    free(buffer); 

    return 0; 
} 

РЕЗУЛЬТАТ

> ./a.out 
abcdefg 
abcdefg 
hijklmn 
abcdefghijklmn 
opqrstu 
abcdefghijklmnopqrstu 
> 
+0

Спасибо вам за ваше объяснение! Но длина буфера неизвестна –

+0

Спасибо, @ t4Planeur, что объясняет указатель double char ** - нам нужно использовать 'realloc()' и заменить выделенную память, если она недостаточна. Я соответствующим образом пересмотрел свой пример. – cdlane

+0

Спасибо вам большое! –

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