动态调整缓冲区大小 [英] Dynamically resizing a buffer

查看:109
本文介绍了动态调整缓冲区大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Hello clc,


我写的程序中有一个缓冲区。缓冲区具有

只写,unsigned-char-at-atime访问权限,并且所需的空间量b / b $ b不是先验的。因此我希望缓冲区使用realloc()动态增长。


理查德希思菲尔德在一个帖子中的评论提示一个好的

算法是使用realloc()来加倍缓冲区的大小,

但是如果realloc()失败请求更小的增量直到realloc()

成功或直到realloc()无法通过一个字节来增加缓冲区




基本思路如下。关键功能是MyBuffer_writebyte(),

期望传入的MyBuffer对象处于一致状态。


我是否可以对此进行任何改进码?对我而言,感觉很笨拙,特别是在3行while循环中断。


struct mybuffer_t {

unsigned char * data;

size_t size; / *分配的缓冲区大小* /

size_t index; / *第一个未写入数据成员的索引* /

};


typedef struct mybuffer_t MyBuffer;


void MyBuffer_writebyte(MyBuffer * buf,unsigned char byte){

if(buf-> size == buf-> index){

/ *需要分配更多空格* /

size_t inc = buf-> size;

unsigned char * tmp;

while(inc> 0){

tmp = realloc(buf-> data,buf-> size + inc);

if(tmp!= NULL)break; / * break以保留inc * /

inc / = 2;

}

if(tmp == NULL){

/ *无法分配更多空间,打印错误并退出* /

退出(EXIT_FAILURE);

}

buf-> size + = inc;

}

buf-> data [buf-> index ++] = byte;

}


-

Philip Potter pgp< atdoc.ic.ac.uk

Hello clc,

I have a buffer in a program which I write to. The buffer has
write-only, unsigned-char-at-a-time access, and the amount of space
required isn''t known a priori. Therefore I want the buffer to
dynamically grow using realloc().

A comment by Richard Heathfield in a thread here suggested that a good
algorithm for this is to use realloc() to double the size of the buffer,
but if realloc() fails request smaller size increments until realloc()
succeeds or until realloc() has failed to increase the buffer by even
one byte.

The basic idea is below. The key function is MyBuffer_writebyte(), which
expects the incoming MyBuffer object to be in a consistent state.

Are there any improvements I could make to this code? To me it feels
clumsy, especially with the break in the 3-line while loop.

struct mybuffer_t {
unsigned char *data;
size_t size; /* size of buffer allocated */
size_t index; /* index of first unwritten member of data */
};

typedef struct mybuffer_t MyBuffer;

void MyBuffer_writebyte(MyBuffer *buf, unsigned char byte) {
if(buf->size == buf->index) {
/* need to allocate more space */
size_t inc = buf->size;
unsigned char *tmp;
while(inc>0) {
tmp = realloc(buf->data, buf->size + inc);
if (tmp!=NULL) break; /* break to preserve the size of inc*/
inc/=2;
}
if(tmp==NULL) {
/* couldn''t allocate any more space, print error and exit */
exit(EXIT_FAILURE);
}
buf->size += inc;
}
buf->data[buf->index++] = byte;
}

--
Philip Potter pgp <atdoc.ic.ac.uk

推荐答案

Philip Potter写道:
Philip Potter wrote:

>

struct mybuffer_t {

unsigned char * data;

size_t size; / *分配的缓冲区大小* /

size_t index; / *第一个未写入数据成员的索引* /

};


typedef struct mybuffer_t MyBuffer;


void MyBuffer_writebyte(MyBuffer * buf,unsigned char byte){

if(buf-> size == buf-> index){

/ *需要分配更多空格* /

size_t inc = buf-> size;

unsigned char * tmp;

while(inc> 0){

tmp = realloc(buf-> data,buf-> size + inc);

if(tmp!= NULL)break; / * break以保留inc * /

inc / = 2;

}

if(tmp == NULL){

/ *无法分配更多空间,打印错误并退出* /

退出(EXIT_FAILURE);

}
>
struct mybuffer_t {
unsigned char *data;
size_t size; /* size of buffer allocated */
size_t index; /* index of first unwritten member of data */
};

typedef struct mybuffer_t MyBuffer;

void MyBuffer_writebyte(MyBuffer *buf, unsigned char byte) {
if(buf->size == buf->index) {
/* need to allocate more space */
size_t inc = buf->size;
unsigned char *tmp;
while(inc>0) {
tmp = realloc(buf->data, buf->size + inc);
if (tmp!=NULL) break; /* break to preserve the size of inc*/
inc/=2;
}
if(tmp==NULL) {
/* couldn''t allocate any more space, print error and exit */
exit(EXIT_FAILURE);
}



你永远不会替换buf->数据......它将继续指向原来的

空间,这可能已被释放...

You never replace buf->data... It will continue to point to the original
space, which may have been freed ...


buf-> size + = inc;

}

buf-> data [buf-> ; index ++] = byte;

}
buf->size += inc;
}
buf->data[buf->index++] = byte;
}



我将调整大小分成单独的函数,因为它是

可推广技术。


你可以结合两种形式的循环控制(增量大小,

分配成功/失败)在这期间。


这个(未经测试的)是我粗暴的黑客: -


void MyBuffer_writebyte(MyBuffer * buf,unsigned char b yte){

if(buf-> size == buf-> index){

if(!resizeBuffer(buf)){

退出(EXIT_FAILURE); / *或更好的错误处理* /

}

}

buf-> data [buf-> index ++] = byte;

}


/ *返回新尺寸* /

int resizeBuffer(MyBuffer * buf){

size_t inc = buf-> size;

unsigned char * tmp = NULL;

while(inc> 0&&

(tmp = realloc(buf-> data,buf-> size + inc))== NULL){

inc / = 2;

}

if(tmp!= NULL){

buf-> data = tmp;

buf-> size + = inc;

返回buf->尺寸;

}否则{

返回0;

}

}

I''d split out the resizing to a separate function, as it''s a
generalizable technique.

You could combine the two forms of loop control (size of increment,
success/failure of allocation) in the while.

This (untested) is my rough hack :-

void MyBuffer_writebyte(MyBuffer *buf, unsigned char byte) {
if(buf->size == buf->index) {
if(!resizeBuffer(buf)){
exit(EXIT_FAILURE); /* or some better error handling */
}
}
buf->data[buf->index++] = byte;
}

/* returns new size */
int resizeBuffer(MyBuffer *buf) {
size_t inc = buf->size;
unsigned char *tmp = NULL;
while(inc>0 &&
(tmp = realloc(buf->data, buf->size + inc)) == NULL) {
inc/=2;
}
if(tmp!=NULL) {
buf->data = tmp;
buf->size += inc;
return buf->size;
} else {
return 0;
}

}


Philip Potter< pg *@see.sig.invalidwrites:
Philip Potter <pg*@see.sig.invalidwrites:

你好clc,


我写的一个程序中有一个缓冲区。缓冲区具有

只写,unsigned-char-at-atime访问权限,并且所需的空间量b / b $ b不是先验的。因此我希望缓冲区使用realloc()动态增长。


理查德希思菲尔德在一个帖子中的评论提示一个好的

算法是使用realloc()来加倍

缓冲区的大小,但是如果realloc()失败请求更小的增量直到

realloc( )成功或直到realloc()未能将

缓冲区增加一个字节。
Hello clc,

I have a buffer in a program which I write to. The buffer has
write-only, unsigned-char-at-a-time access, and the amount of space
required isn''t known a priori. Therefore I want the buffer to
dynamically grow using realloc().

A comment by Richard Heathfield in a thread here suggested that a good
algorithm for this is to use realloc() to double the size of the
buffer, but if realloc() fails request smaller size increments until
realloc() succeeds or until realloc() has failed to increase the
buffer by even one byte.



是缓冲区大小的两倍?永远不要IMO。如果你设计不是缓冲区

是关于正确的首先。假设它没有失败,但确实耗尽了b $ b排气记忆?好吧,爆炸你的下一个malloc。


保持简单。增加delta并使用它。我建议

类似于初始大小的10-20%。


显然,如果你知道缓冲区要翻倍/四倍等等/>
然后malloc它开始。

Double the size of the buffer? Never IMO. Not if you "designed" the buffer
to be "about right" in the first place. Suppose it doesn''t fail but does
exhaust memory? Well, bang goes your next malloc.

Keep it simple. Have a delta increase and use that. I would suggest
something like 10-20% of the initial size.

Clearly if you KNOW that the buffer is going to double/quadruple etc
then malloc it to start with.


>

基本思路如下。关键功能是MyBuffer_writebyte(),

,它希望传入的MyBuffer对象处于一致的

状态。


Are我可以对此代码进行任何改进吗?对我而言,感觉很笨拙,特别是在3行while循环中断。


struct mybuffer_t {

unsigned char * data;

size_t size; / *分配的缓冲区大小* /

size_t index; / *第一个未写入数据成员的索引* /

};


typedef struct mybuffer_t MyBuffer;


void MyBuffer_writebyte(MyBuffer * buf,unsigned char byte){

if(buf-> size == buf-> index){

/ *需要分配更多空格* /

size_t inc = buf-> size;

unsigned char * tmp;

while(inc> 0){

tmp = realloc(buf-> data,buf-> size + inc);

if(tmp!= NULL)break; / * break以保留inc * /

inc / = 2;

}

if(tmp == NULL){

/ *无法分配更多空间,打印错误并退出* /

退出(EXIT_FAILURE);

}

buf-> size + = inc;

}

buf-> data [buf-> index ++] = byte;

}
>
The basic idea is below. The key function is MyBuffer_writebyte(),
which expects the incoming MyBuffer object to be in a consistent
state.

Are there any improvements I could make to this code? To me it feels
clumsy, especially with the break in the 3-line while loop.

struct mybuffer_t {
unsigned char *data;
size_t size; /* size of buffer allocated */
size_t index; /* index of first unwritten member of data */
};

typedef struct mybuffer_t MyBuffer;

void MyBuffer_writebyte(MyBuffer *buf, unsigned char byte) {
if(buf->size == buf->index) {
/* need to allocate more space */
size_t inc = buf->size;
unsigned char *tmp;
while(inc>0) {
tmp = realloc(buf->data, buf->size + inc);
if (tmp!=NULL) break; /* break to preserve the size of inc*/
inc/=2;
}
if(tmp==NULL) {
/* couldn''t allocate any more space, print error and exit */
exit(EXIT_FAILURE);
}
buf->size += inc;
}
buf->data[buf->index++] = byte;
}



-

--


Richard写道:
Richard wrote:

Philip Potter< pg*@see.sig.invalidwrites:
Philip Potter <pg*@see.sig.invalidwrites:

> Hello clc,

我有我写的程序中的缓冲区。缓冲区具有只写,无符号一次访问,并且所需的空间量不是先验的。因此,我希望缓冲区能够使用realloc()动态增长。

理查德·希思菲尔德在一个帖子中的评论表明,一个好的算法就是使用realloc( )将
缓冲区的大小加倍,但是如果realloc()失败请求更小的增量,直到
realloc()成功或者直到realloc()无法增加
缓冲区字节。
>Hello clc,

I have a buffer in a program which I write to. The buffer has
write-only, unsigned-char-at-a-time access, and the amount of space
required isn''t known a priori. Therefore I want the buffer to
dynamically grow using realloc().

A comment by Richard Heathfield in a thread here suggested that a good
algorithm for this is to use realloc() to double the size of the
buffer, but if realloc() fails request smaller size increments until
realloc() succeeds or until realloc() has failed to increase the
buffer by even one byte.



是缓冲区大小的两倍?永远不要IMO。如果你设计不是缓冲区

是关于正确的首先。假设它没有失败,但确实耗尽了b $ b排气记忆?好吧,爆炸你的下一个malloc。


保持简单。增加delta并使用它。我建议

类似于初始大小的10-20%。


显然,如果你知道缓冲区要翻倍/四倍等等/>
然后将malloc开始。


Double the size of the buffer? Never IMO. Not if you "designed" the buffer
to be "about right" in the first place. Suppose it doesn''t fail but does
exhaust memory? Well, bang goes your next malloc.

Keep it simple. Have a delta increase and use that. I would suggest
something like 10-20% of the initial size.

Clearly if you KNOW that the buffer is going to double/quadruple etc
then malloc it to start with.



我已经说过,所需的最终空间数量是不知道的。

a priori。它可能是数千字节,可能是数百万字节。一个

线性增长缓冲区不适合这种情况,这就是为什么我选择了指数增长的缓冲区。


Phil


-

Philip Potter pgp< atdoc.ic.ac.uk

I''ve already stated that the final amount of space required isn''t known
a priori. It could be thousands of bytes, it could be millions. A
linearly-growing buffer is not appropriate for this situation, which is
why I chose an exponentially-growing buffer.

Phil

--
Philip Potter pgp <atdoc.ic.ac.uk


这篇关于动态调整缓冲区大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆