Кодирование getline () имплантации – ошибки Valgrind

Я должен перекодировать реализацию функции getline() , но используя файловый дескриптор файла, а не FILE * . Мне разрешено использовать malloc() и free() , а также 5 функций, максимум 25 строк длиной. Я думаю, что я правильно сделал проект, хотя я новичок в C, и мой код, вероятно, не хорош.

Когда я запускаю его, он работает нормально, но valgrind показывает, что я определенно definetely lost x bytes , x в зависимости от длины файла и READ_SIZE (макрос, определенный в заголовке).

По --leak-check=full , у меня есть утечка памяти в функции str_realloc_cat , когда я malloc dest . Я пытался, но не мог найти, где я должен освободить / сделать что-то еще?

Ниже приведен мой код:

 char *get_next_line(const int fd) { static char *remaining = ""; char *buffer; ssize_t cread; size_t i; i = 0; if (remaining == NULL) return (NULL); if ((buffer = malloc(SOF(char) * READ_SIZE + 1)) == NULL || (cread = read(fd, buffer, READ_SIZE)) < 0) return (NULL); buffer[cread] = 0; remaining = str_realloc_cat(remaining, buffer); while (remaining[i]) { if (remaining[i] == 10) { remaining[i] = 0; buffer = str_create_cpy(remaining); remaining = remaining + i + 1; return (buffer); } i++; } return (check_eof(fd, buffer, remaining, cread)); } char *str_realloc_cat(char *rem, char *buf) { size_t i; size_t dest_i; char *dest; i = (dest_i = 0); if ((dest = malloc(SOF(char) * (str_len(rem) + str_len(buf) + 1))) == NULL) return (NULL); while (rem[i]) { dest[dest_i] = rem[i]; dest_i++; i++; } i = 0; while (buf[i]) { dest[dest_i] = buf[i]; dest_i++; i++; } dest[dest_i] = 0; free(buf); return (dest); } char *check_eof(const int fd, char *buffer, char *remaining, ssize_t cread) { if (cread == 0) return (NULL); if (cread < READ_SIZE) { buffer = remaining; remaining = NULL; return (buffer); } return (get_next_line(fd)); } char *str_create_cpy(const char *src) { char *dest; size_t i; i = 0; if ((dest = malloc(sizeof(char) * str_len(src) + 1)) == NULL) return (NULL); while (src[i]) { dest[i] = src[i]; i++; } dest[i] = 0; return (dest); } int str_len(const char *str) { size_t i; i = 0; while (str[i]) i++; return (i); } 

И главное, если вы хотите протестировать:

 #define SOF(x) sizeof(x) // Why in the comments int main(int ac, char **av) { int fd; char *s; UNUSED(ac); if (!av[1]) return 1; fd = open(av[1], O_RDONLY); while ((s = get_next_line(fd))) { printf("%s\n", s); free(s); } close(fd); } 

Благодаря любой помощи или советам.

Ваш алгоритм плох:

  1. Вы сохраняете буфер в памяти распределения
  2. Вы не используете структуру для перегруппировки переменной
  3. Вы используете remaining[i] == 10 магическое число remaining[i] == 10
  4. Вы используете рекурсивный, вы можете переполнять return get_next_line(fd) переполнения return get_next_line(fd) . Неважно, я не хорошо читал, у вас есть хвост рекурсивный, просто убедитесь, что оптимизация на вашем компиляции для него.
  5. У вас есть код спагетти.
  6. и т.п.

Вы должны переписать всю свою функцию с лучшей логикой, сначала используйте эту структуру:

 #include  #include  #include  #include  #define GNL_SIZE 4096 struct gnl_context { char buffer[GNL_SIZE]; size_t i; size_t read; }; char *get_next_line_r(int fd, struct gnl_context *gnl_context); char *get_next_line(int fd); static char *read_buffer(struct gnl_context *gnl_context, char *str, size_t *size) { size_t i = gnl_context->i; while (i < gnl_context->read && gnl_context->buffer[i] != '\n') { i++; } size_t j = i - gnl_context->i; char *ret = realloc(str, *size + j + 1); if (ret == NULL) { return NULL; } memcpy(ret + *size, gnl_context->buffer + gnl_context->i, j); *size += j; ret[*size] = '\0'; gnl_context->i = i; return ret; } char *get_next_line_r(int fd, struct gnl_context *gnl_context) { char *str = NULL; size_t size = 0; loop: if (gnl_context->i == gnl_context->read) { ssize_t ret = read(fd, gnl_context->buffer, GNL_SIZE); if (ret <= 0) { return str; } gnl_context->read = (size_t)ret; gnl_context->i = 0; } char *tmp = read_buffer(gnl_context, str, &size); if (tmp == NULL) { return str; } if (gnl_context->i != gnl_context->read) { gnl_context->i++; return tmp; } str = tmp; goto loop; } char *get_next_line(int fd) { static struct gnl_context gnl_context; return get_next_line_r(fd, &gnl_context); } int main(void) { char *str; while ((str = get_next_line(0)) != NULL) { printf("%s\n", str); free(str); } } 

Меня беспокоит эта линия:

 remaining = remaining + i + 1; 

remaining – указатель на выделенный буфер. На этой линии вы уничтожаете ее, а это значит, что вы больше не можете ее free() .