如何使用 read() 增加动态缓冲区?

How do I grow a dynamic buffer with read()?

所以我在考虑增加缓冲区时遇到了一些麻烦,从我所看到的情况来看,我肯定是在从文件描述符中读取所有字节,但似乎我没有存储它们在缓冲区中正确。有人可以帮我指明正确的方向吗?

char *read_all(int fd, int *nread){ //nread tracks total bytes read
  int max_size = 1;
  *nread = 0;
  char *buf = malloc(max_size*sizeof(char));
  int bytes_read = read(fd, buf, max_size*sizeof(char));
  while(bytes_read > 0){ 
    *nread+=bytes_read;
    if(*nread >= max_size*sizeof(char)){
      max_size*=2;
      buf = realloc(buf, max_size*sizeof(char));
    }
    bytes_read = read(fd, buf, max_size*sizeof(char));
  }
  return buf;
}
==== EXPECT ====                                                       ==== ACTUAL ====                                                    
{                                                                      {
    // Tests the read_all() function to ensure that                        // Tests the read_all() function to ensure that
    // it properly accumulates all data from an                            // it properly accumulates all data from an
    // arbitrary input FD including allocating memory                      // arbitrary input FD including allocating memory
    // for the data.                                                       // for the data. 
    int fd = open("test-data/quote.txt", O_RDONLY);                        int fd = open("test-data/quote.txt", O_RDONLY);
    int bytes_read = -1;                                                   int bytes_read = -1;
    char *actual_read = read_all(fd, &bytes_read);                         char *actual_read = read_all(fd, &bytes_read);
    int result = close(fd);                                                int result = close(fd);
    printf("result: %d\n", result);                                        printf("result: %d\n", result);
    printf("bytes_read: %d\n", bytes_read);                                printf("bytes_read: %d\n", bytes_read);
    actual_read[bytes_read] = '[=11=]';                                        actual_read[bytes_read] = '[=11=]';
    printf("actual_read:\n" );                                             printf("actual_read:\n" );
    printf("--------------------\n" );                                     printf("--------------------\n" );
    printf("%s",actual_read);                                              printf("%s",actual_read);
    printf("--------------------\n" );                                     printf("--------------------\n" );
    free(actual_read);                                                     free(actual_read);
}                                                                      }
result: 0                                                              result: 0
bytes_read: 125                                                        bytes_read: 125
actual_read:                                                           actual_read:
--------------------                                                   --------------------
Object-oriented programming is an exceptionally bad idea which could | could
only have originated in California.                                    only have originated in California.

-- Edsger Dijkstra                                                     -- Edsger Dijkstra
--------------------                                                   --------------------
ALERTS:                                                                ALERTS:
                                                                     (

有点奇怪…… 我更改了 read_all() 所以它更像预期的那样工作:(full here)

char *read_all2(int fd, int *nread){ //nread tracks total bytes read
  int max_size = 1;
  *nread = 0;
  char *buf = malloc(max_size*sizeof(char));
  char *ptr = buf;
  int bytes_read = 0;
  //while(bytes_read > 0)
  do
  {
    fprintf(stderr, "bytes_read=%d\n", bytes_read);
    *nread += bytes_read;
    ptr += bytes_read;
    if(*nread >= max_size*1){
      max_size *= 2;
      fprintf(stderr, "realloc(buf=%08x, max_size=%d)\n", buf, max_size);
      buf = realloc(buf, max_size*1);
    }
  } while((bytes_read = read(fd, ptr, max_size*1)) > 0);
  return buf;
}

但是当它 realloc(buf, 16); 它崩溃了。

$ gcc -o readynbuf2 readynbuf2.c ; ./readynbuf2
bytes_read=0
bytes_read=1
realloc(buf=016ba008, max_size=2)
bytes_read=2
realloc(buf=016ba008, max_size=4)
bytes_read=4
realloc(buf=016ba008, max_size=8)
bytes_read=8
realloc(buf=016ba008, max_size=16)
*** Error in `./readynbuf2': realloc(): invalid next size: 0x016ba008 ***

我不知道为什么会这样。

谢谢大家,我设法解决了,关键是将 &buf[*nread] 传递给 read()。

char *read_all(int fd, int *nread){
  int bytes_read = 0, size_mult = 1;
  *nread = 0;
  char * buf = malloc(1024);
  bytes_read = read(fd, &buf[*nread], 256);
  while(bytes_read > 0){
    *nread += bytes_read;
    if(*nread > size_mult*512){
      size_mult*=2;
      buf = realloc(buf, size_mult*1024);
    }
    bytes_read = read(fd, &buf[*nread], 256);
  }
  return buf;
}