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