Coding a getline() implementation - Valgrind errors

隐身守侯 提交于 2019-11-29 18:02:30

Your algorithm is bad:

  1. You keep the buffer in a allocate memory
  2. You don't use a structure to regroup your variable
  3. You use magic number remaining[i] == 10
  4. You use recursive you can stack overflow return get_next_line(fd). Never mind, I didn't read well you have a tail recursive, just be sure to have the optimization on your compile for it.
  5. You have Spaghetti code.
  6. etc.

You should rewrite your whole function with a better logic first use this structure:

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

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

I am concerned about this line:

remaining = remaining + i + 1;

remaining is a pointer to the allocated buffer. On this line, you destroy it, which means that you cannot free() it anymore.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!