扩展缓冲区 - 对“确定malloc的大小”的响应询问 [英] Expanding buffer - response to "Determine the size of malloc" query

查看:81
本文介绍了扩展缓冲区 - 对“确定malloc的大小”的响应询问的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

初始问题:读取任意长度的文本。

感知问题:处理可变长度数据


以下代码是建议用于实现可变长度

缓冲区,可用于读取文本或处理任意长度为b
的数组。我没有这里很多人的C专业知识,所以我觉得

就像我提供一个小毛茸茸的动物牺牲大装甲

镀一个...但无论如何都会提供它。请建议改进​​

或挑战前提。如果可以改进它将会很棒。

成为一个通常有用的代码。


嗯,这里有。这应该是有趣的。 : - ?


-


以下实用程序代码传递缓冲区(由

调用者分配)并保持适当的大小。主要功能

增加分配(必要时)的因素 - 而不是

固定金额 - 以提高速度。有一个辅助功能可以将

缓冲区修剪回特定大小。总是留下一个额外的字节(比请求
多一个)。


/ *

*扩展缓冲区

* /


#define EBUF_SIZE_INIT 128

#define EBUF_SIZE_MIN 128

#define EBUF_INCREASE 1.5 / *每次增加空间的因素* /


#include< stdio.h>

#include< stdlib.h>

#include< malloc.h>


int ebuf_full(char ** buf,size_t * buf_size,size_t offset){

size_t new_size;

char * new_buf;


if(* buf_size< offset + 2){/ * NB last pos left empty * /

new_size = * buf_size * EBUF_INCREASE + 1;

if(new_size< offset + 2)new_size = offset + 2;

if(new_size< EBUF_SIZE_MIN )new_size = EBUF_SIZE_MIN;

if((new_buf = realloc(* buf,new_size))== NULL){

返回1; / *无法重新分配缓冲区* /

}

* buf = new_buf;

* buf_size = new_size;

}

返回0; / *成功重新分配* /

}

int ebuf_trim(char ** buf,size_t * buf_size,size_t offset){

int new_size =偏移+ 2; / *包括空字符* /

字符* new_buf;


if(new_size< EBUF_SIZE_MIN)new_size = EBUF_SIZE_MIN;

if(new_size!= * buf_size){

if((new_buf = realloc(* buf,new_size))== NULL){

返回1; / *重新分配失败(不太可能)* /

}

* buf = new_buf;

* buf_size = new_size;

}

返回0; / *重新分配成功* /

}

解决方案

5月30日,14:12,James Harris < james.harri ... @ googlemail.comwrote:


初始问题:读取任意长度的文本。

感知问题:处理可变长度数据


以下代码是实现可变长度

缓冲区的建议,可用于读取文本或处理数组任意

长度。我没有这里很多人的C专业知识,所以我觉得

就像我提供一个小毛茸茸的动物牺牲大装甲

镀一个...但无论如何都会提供它。请建议改进​​

或挑战前提。如果可以改进它将会很棒。

成为一个通常有用的代码。


嗯,这里有。这应该是有趣的。 : - ?


-


以下实用程序代码传递缓冲区(由

调用者分配)并保持适当的大小。主要功能

增加分配(必要时)的因素 - 而不是

固定金额 - 以提高速度。有一个辅助功能可以将

缓冲区修剪回特定大小。总是留下一个额外的字节(比请求
多一个)。


/ *

*扩展缓冲区

* /


#define EBUF_SIZE_INIT 128

#define EBUF_SIZE_MIN 128

#define EBUF_INCREASE 1.5 / *每次增加空间的因素* /


#include< stdio.h>

#include< stdlib.h>

#include< malloc.h>


int ebuf_full(char ** buf,size_t * buf_size,size_t offset){

size_t new_size;

char * new_buf;


if(* buf_size< offset + 2){/ * NB last pos left empty * /

new_size = * buf_size * EBUF_INCREASE + 1;

if(new_size< offset + 2)new_size = offset + 2;

if(new_size< EBUF_SIZE_MIN )new_size = EBUF_SIZE_MIN;

if((new_buf = realloc(* buf,new_size))== NULL){

返回1; / *无法重新分配缓冲区* /

}

* buf = new_buf;

* buf_size = new_size;

}

返回0; / *成功重新分配* /


}


int ebuf_trim(char ** buf,size_t * buf_size,size_t offset){

int new_size = offset + 2; / *包括空字符* /

字符* new_buf;


if(new_size< EBUF_SIZE_MIN)new_size = EBUF_SIZE_MIN;

if(new_size!= * buf_size){

if((new_buf = realloc(* buf,new_size))== NULL){

返回1; / *重新分配失败(不太可能)* /

}

* buf = new_buf;

* buf_size = new_size;

}

返回0; / *重新分配成功* /


}



以下是预期用途的示例。请注意,例程编码为
,以期望缓冲区和当前大小作为参数。尽管错误

处理代码的目的很快。包括if(offset + 2>

buf1_size)"在主代码中,只有在

缓冲区太小的情况下才能调用该函数。一整数比较的成本很小。


int main(){

char * buf1;

size_t buf1_size = EBUF_SIZE_INIT ;

size_t offset;


if((buf1 = malloc(buf1_size))== NULL){

fprintf(stderr) ,缓冲区初始malloc%d字节失败\ nn,

buf1_size);

退出(1);

} < br $>

...


offset =<要写入的缓冲区中的位置>


。 ..


/ *检查buf1足够大* /

if(offset + 2 buf1_size&& ebuf_full(& buf1,& buf1_size) ,偏移))

{

fprintf(stderr,缓冲区溢出 - 有%d字节,但需要%d

字节,

buf1_size,偏移+ 2);

退出(1);

}

buf1 [偏移] = 0 ;


...


免费(buf1);

}


5月30日14:12,James Harris< james.harri ... @ googlemail.c omwrote:


初始问题:读取任意长度的文本。

感知问题:处理可变长度数据


以下代码建议实现一个可变长度的
缓冲区,可用于读取文本或处理任意长度为
的数组。我没有这里很多人的C专业知识,所以我觉得

就像我提供一个小毛茸茸的动物牺牲大装甲

镀一个...但无论如何都会提供它。请建议改进​​

或挑战前提。如果可以改进它将会很棒。

成为一个通常有用的代码。


嗯,这里有。这应该是有趣的。 : - ?


-


以下实用程序代码传递缓冲区(由

调用者分配)并保持适当的大小。主要功能

增加分配(必要时)的因素 - 而不是

固定金额 - 以提高速度。有一个辅助功能可以将

缓冲区修剪回特定大小。总是留下一个额外的字节(比请求
多一个)。


/ *

*扩展缓冲区

* /


#define EBUF_SIZE_INIT 128

#define EBUF_SIZE_MIN 128

#define EBUF_INCREASE 1.5 / *每次增加空间的因素* /


#include< stdio.h>

#include< stdlib.h>

#include< malloc.h>


int ebuf_full(char ** buf,size_t * buf_size,size_t offset){

size_t new_size;

char * new_buf;


if(* buf_size< offset + 2){/ * NB last pos left empty * /

new_size = * buf_size * EBUF_INCREASE + 1;

if(new_size< offset + 2)new_size = offset + 2;

if(new_size< EBUF_SIZE_MIN )new_size = EBUF_SIZE_MIN;

if((new_buf = realloc(* buf,new_size))== NULL){

返回1; / *无法重新分配缓冲区* /

}

* buf = new_buf;

* buf_size = new_size;

}

返回0; / *成功重新分配* /


}


int ebuf_trim(char ** buf,size_t * buf_size,size_t offset){

int new_size = offset + 2; / *包括空字符* /

字符* new_buf;


if(new_size< EBUF_SIZE_MIN)new_size = EBUF_SIZE_MIN;

if(new_size!= * buf_size){

if((new_buf = realloc(* buf,new_size))== NULL){

返回1; / *重新分配失败(不太可能)* /

}

* buf = new_buf;

* buf_size = new_size;

}

返回0; / *重新分配成功* /


}



这是使用建议函数的另一段示例代码。

这个是读取任意长度的行。希望将

与自定义行读取功能进行比较时,下面的代码保留了更简单的

接口,同时允许任何必要的选项。它也应该很快

,再次,只有在需要更多空间时才会调用该函数。由于函数在大多数迭代中不断增加的内存中分配内存,因此不会调用该函数。

#define ENDCHAR''\ n''


FILE * infile = stdin;

char * buffer;

size_t bufsize = 100; / *仅初始尺寸* /

size_t偏移;


...(分配缓冲区)


/ *读取''endchar''* /

for(offset = 0;(ch = getc(infile))!= EOF;){

if(offset + 2 bufsize&&

ebuf_full(& buffer,& bufsize,offset){

fprintf(stderr,Line too long for memory);

退出(1);

}

buffer [offset ++] = ch;

if(ch == ENDCHAR )休息;

}


...(免费缓冲区)


值得注意的是,因为我们调用了getc()如果(ch ==''\ n''|| ch ==''我们可以很容易地拥有多个

终止字符,例如


\ 0''|| ch =='','')


等,这比打电话更有优势

读者功能。


-

James


James Harris写道:
< blockquote class =post_quotes>
5月30日14:12,James Harris< james.harri ... @ googlemail.comwrote:


>初始问题:以任意长度读取一段文字。
感知问题:处理可变长度数据

下面的代码是一个实现可变长度缓冲区的建议,可用于读取文本或处理数组任意长度。我没有在这里很多人的C专业知识,所以我觉得我喜欢提供一个小毛茸茸的动物牺牲一个大盔甲
镀一个...但会提供它无论如何。请建议改进​​
或挑战前提。如果可以改进它将成为一个通用的代码片段会很棒。

嗯,这里有。这应该是有趣的。 : - ?


以下实用程序代码传递一个缓冲区(由
调用者分配)并保持适当的大小。主要功能
通过因子(而不是固定数量)增加分配(必要时)以提高速度。有一个辅助功能可以将
缓冲区修剪回特定大小。总是留下一个额外的字节(比
要多一个)。

/ *
*扩展缓冲区
* /

#define EBUF_SIZE_INIT 128
#define EBUF_SIZE_MIN 128
#define EBUF_INCREASE 1.5 / *每次增加空间的因素* /

#include< stdio.h>
#include< stdlib.h>
#include< malloc.h>



只有一只小型毛茸茸的动物为牺牲而牺牲

会使用非标准的标题,例如< malloc .H取代。考虑一下你自己被贪婪的Bugblatter野兽吃掉了。


另外,似乎没有理由< stdio.hin

缓冲区代码; #include无关

行李并没有什么坏处,但它也没有帮助。你需要的一切

在< stdlib.h>中。


> int ebuf_full(char ** buf,size_t * buf_size,size_t offset){
size_t new_size;
char * new_buf;

if(* buf_size< offset + 2){/ * NB last pos left empty * /



这个神奇的2出现在很多地方。也许

它应该有#define吗?


> new_size = * buf_size * EBUF_INCREASE + 1;



作为个人偏好和偏见的小问题,

我自己会在这里避免浮点运算并且做

整数计算。不过没什么大不了的。


> if(new_size< offset + 2)new_size = offset + 2;
if(new_size< EBUF_SIZE_MIN)new_size = EBUF_SIZE_MIN;
if((new_buf = realloc(* buf,new_size))== NULL ){
返回1; / *无法重新分配缓冲区* /
}
* buf = new_buf;
* buf_size = new_size;
}
返回0; / *重新分配成功* /


int ebuf_trim(char ** buf,size_t * buf_size,size_t offset){
int new_size = offset + 2; / *包括空char * /
char * new_buf;

if(new_size< EBUF_SIZE_MIN)new_size = EBUF_SIZE_MIN;
if(new_size!= * buf_size){
if((new_buf = realloc(* buf,new_size))== NULL){
返回1; / *重新分配失败(不太可能)* /



这里有潜在的界面设计决策:应该

这个被视为失败,或只是不成功

尝试优化?可以对两个点进行争论

。恕我直言,你已经选择了正确的,因为ebuf_trim()可能会失败,试图*增加缓冲区的大小* b $ b,这是可能的。在哪种情况下,调用程序可能会因为发现缓冲区太小而感到惊讶

的偏移量。


> } * /> * buf = new_buf;
* buf_size = new_size;
}
返回0; / *重新分配成功* /

}



以下是预期用途的示例。请注意,例程编码为
,以期望缓冲区和当前大小作为参数。尽管错误

处理代码的目的很快。包括if(offset + 2>

buf1_size)"在主代码中,只有在

缓冲区太小的情况下才能调用该函数。一个整数比较的成本很小。


int main(){



`int main(void)''会更好一点。


char * buf1;

size_t buf1_size = EBUF_SIZE_INIT;

size_t offset;


if((buf1 = malloc(buf1_size))== NULL){

fprintf(stderr,"%d字节的缓冲区初始malloc失败了\\ n,

buf1_size);



buf1_size的类型是什么?答案:size_t。

操作数是什么类型的%d说明符转换?答案:int。

size_t和int相同吗?答:不。你应该怎么做?
修复不匹配问题?答案:更改%d至%g。 (不,等等,我

并不意味着...)


对于fprintf()等等,< stdio.h * *需要。


exit(1);



ITYM`export(EXIT_FAILURE);''。或者`return EXIT_FAILURE;''。


}



而不是预先分配初始缓冲区,为什么不

设置buf1 = NULL和buf1_size = 0并让ebuf_full()

处理所有事情?


...


offset =<缓冲区中的位置写入>


...


/ *检查buf1足够大* /

if(offset + 2 buf1_size&& ebuf_full(& buf1,& buf1_size,offset))

{

fprintf(stderr,缓冲区溢出 - 有%d字节,但需要%d

字节,

buf1_size ,偏移+ 2);

退出(1);

}

buf1 [offset] = 0;


...


免费(buf1);



...并且由于main()返回一个int值,你应该......?

(C99引入了一条特殊规则main()表示下降

最终相当于返回零,但恕我直言这个

应该被视为对大量草率的让步

代码已经存在,并不是为了进一步鼓励
邋iness。此外,C99的实现并没有完全被风暴带走的世界和大量的C90实现是

仍然在使用。)


}



似乎对我来说,你理解如何使用realloc()来增长缓冲区的基本思路(尽管你可以重新分配一个空的事实可能已经逃脱了你)。你做的事情有一些很小的故障,很容易解决。


如果你想打包这样的东西更广泛的/>
用作缓冲区管理实用程序,您可以考虑将

缓冲区信息放在struct中,并将单个

结构指针传递给函数。通过减少参数计数,这不仅可以使界面更清晰,而且还可以让你更容易添加更多的填充物

稍后的功能,只需在结构中添加一些元素

并单独留下电话。


回到你的巢穴并舔你的伤口;我想

他们没有生命危险。


-
Er ********* @ sun.com


Initial issue: read in an arbitrary-length piece of text.
Perceived issue: handle variable-length data

The code below is a suggestion for implementing a variable length
buffer that could be used to read text or handle arrays of arbitrary
length. I don''t have the expertise in C of many folks here so I feel
like I''m offering a small furry animal for sacrifice to a big armour
plated one... but will offer it anyway. Please do suggest improvements
or challenge the premise. It would be great if it could be improved to
become a generally useful piece of code.

Well, here goes. This should be fun. :-?

-

The following utility code is passed a buffer (allocated by the
caller) and maintains it at an appropriate size. The main function
increases the allocation (when necessary) by factors - rather than
fixed amounts - for speed. There is a secondary function to trim a
buffer back to a specific size. An extra byte (one more than is
requested) is always left at the end.

/*
* Expanding buffer
*/

#define EBUF_SIZE_INIT 128
#define EBUF_SIZE_MIN 128
#define EBUF_INCREASE 1.5 /* Factor to increase space by each time */

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

int ebuf_full(char **buf, size_t *buf_size, size_t offset) {
size_t new_size;
char *new_buf;

if (*buf_size < offset + 2) { /* NB last pos left empty */
new_size = *buf_size * EBUF_INCREASE + 1;
if (new_size < offset + 2) new_size = offset + 2;
if (new_size < EBUF_SIZE_MIN) new_size = EBUF_SIZE_MIN;
if ((new_buf = realloc(*buf, new_size)) == NULL) {
return 1; /* Failed to realloc buffer */
}
*buf = new_buf;
*buf_size = new_size;
}
return 0; /* Reallocated successfuly */
}
int ebuf_trim(char **buf, size_t *buf_size, size_t offset) {
int new_size = offset + 2; /* Includes empty char */
char *new_buf;

if (new_size < EBUF_SIZE_MIN) new_size = EBUF_SIZE_MIN;
if (new_size != *buf_size) {
if ((new_buf = realloc(*buf, new_size)) == NULL) {
return 1; /* Reallocation failed (unlikely) */
}
*buf = new_buf;
*buf_size = new_size;
}
return 0; /* Reallocation succeeded */
}

解决方案

On 30 May, 14:12, James Harris <james.harri...@googlemail.comwrote:

Initial issue: read in an arbitrary-length piece of text.
Perceived issue: handle variable-length data

The code below is a suggestion for implementing a variable length
buffer that could be used to read text or handle arrays of arbitrary
length. I don''t have the expertise in C of many folks here so I feel
like I''m offering a small furry animal for sacrifice to a big armour
plated one... but will offer it anyway. Please do suggest improvements
or challenge the premise. It would be great if it could be improved to
become a generally useful piece of code.

Well, here goes. This should be fun. :-?

-

The following utility code is passed a buffer (allocated by the
caller) and maintains it at an appropriate size. The main function
increases the allocation (when necessary) by factors - rather than
fixed amounts - for speed. There is a secondary function to trim a
buffer back to a specific size. An extra byte (one more than is
requested) is always left at the end.

/*
* Expanding buffer
*/

#define EBUF_SIZE_INIT 128
#define EBUF_SIZE_MIN 128
#define EBUF_INCREASE 1.5 /* Factor to increase space by each time */

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

int ebuf_full(char **buf, size_t *buf_size, size_t offset) {
size_t new_size;
char *new_buf;

if (*buf_size < offset + 2) { /* NB last pos left empty */
new_size = *buf_size * EBUF_INCREASE + 1;
if (new_size < offset + 2) new_size = offset + 2;
if (new_size < EBUF_SIZE_MIN) new_size = EBUF_SIZE_MIN;
if ((new_buf = realloc(*buf, new_size)) == NULL) {
return 1; /* Failed to realloc buffer */
}
*buf = new_buf;
*buf_size = new_size;
}
return 0; /* Reallocated successfuly */

}

int ebuf_trim(char **buf, size_t *buf_size, size_t offset) {
int new_size = offset + 2; /* Includes empty char */
char *new_buf;

if (new_size < EBUF_SIZE_MIN) new_size = EBUF_SIZE_MIN;
if (new_size != *buf_size) {
if ((new_buf = realloc(*buf, new_size)) == NULL) {
return 1; /* Reallocation failed (unlikely) */
}
*buf = new_buf;
*buf_size = new_size;
}
return 0; /* Reallocation succeeded */

}

An example of intended use follows. Note that the routines are coded
to expect buffer and current size as parameters. Despite the error
handling the code is intended to be fast. Including "if (offset + 2 >
buf1_size)" in the main code the function should only be called if the
buffer is too small. The cost of one integer comparison is small.

int main() {
char *buf1;
size_t buf1_size = EBUF_SIZE_INIT;
size_t offset;

if ((buf1 = malloc(buf1_size)) == NULL) {
fprintf(stderr, "Buffer initial malloc of %d bytes failed\n",
buf1_size);
exit(1);
}

...

offset = <position in buffer to write to>

...

/* Check buf1 is big enough */
if (offset + 2 buf1_size && ebuf_full(&buf1, &buf1_size, offset))
{
fprintf(stderr, "Buffer overflow - have %d bytes but need %d
bytes",
buf1_size, offset + 2);
exit(1);
}
buf1[offset] = 0;

...

free(buf1);
}


On 30 May, 14:12, James Harris <james.harri...@googlemail.comwrote:

Initial issue: read in an arbitrary-length piece of text.
Perceived issue: handle variable-length data

The code below is a suggestion for implementing a variable length
buffer that could be used to read text or handle arrays of arbitrary
length. I don''t have the expertise in C of many folks here so I feel
like I''m offering a small furry animal for sacrifice to a big armour
plated one... but will offer it anyway. Please do suggest improvements
or challenge the premise. It would be great if it could be improved to
become a generally useful piece of code.

Well, here goes. This should be fun. :-?

-

The following utility code is passed a buffer (allocated by the
caller) and maintains it at an appropriate size. The main function
increases the allocation (when necessary) by factors - rather than
fixed amounts - for speed. There is a secondary function to trim a
buffer back to a specific size. An extra byte (one more than is
requested) is always left at the end.

/*
* Expanding buffer
*/

#define EBUF_SIZE_INIT 128
#define EBUF_SIZE_MIN 128
#define EBUF_INCREASE 1.5 /* Factor to increase space by each time */

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

int ebuf_full(char **buf, size_t *buf_size, size_t offset) {
size_t new_size;
char *new_buf;

if (*buf_size < offset + 2) { /* NB last pos left empty */
new_size = *buf_size * EBUF_INCREASE + 1;
if (new_size < offset + 2) new_size = offset + 2;
if (new_size < EBUF_SIZE_MIN) new_size = EBUF_SIZE_MIN;
if ((new_buf = realloc(*buf, new_size)) == NULL) {
return 1; /* Failed to realloc buffer */
}
*buf = new_buf;
*buf_size = new_size;
}
return 0; /* Reallocated successfuly */

}

int ebuf_trim(char **buf, size_t *buf_size, size_t offset) {
int new_size = offset + 2; /* Includes empty char */
char *new_buf;

if (new_size < EBUF_SIZE_MIN) new_size = EBUF_SIZE_MIN;
if (new_size != *buf_size) {
if ((new_buf = realloc(*buf, new_size)) == NULL) {
return 1; /* Reallocation failed (unlikely) */
}
*buf = new_buf;
*buf_size = new_size;
}
return 0; /* Reallocation succeeded */

}

Here''s another piece of example code to use the proposed functions.
This one is to read an arbitrary-length line. Hopefully when compared
with a custom line-reading function the code below keeps a far simpler
interface while allowing any necessary options. It should also be fast
in that, again, the function only gets called if there is a need for
more space. Since the function allocates memory in ever-increasing
chunks for most iterations the function will not be called.
#define ENDCHAR ''\n''

FILE *infile = stdin;
char *buffer;
size_t bufsize = 100; /* Initial size only */
size_t offset;

... (allocate buffer)

/* Read to ''endchar'' */
for (offset = 0; (ch = getc(infile)) != EOF; ) {
if (offset + 2 bufsize &&
ebuf_full(&buffer, &bufsize, offset) {
fprintf(stderr, "Line too long for memory");
exit(1);
}
buffer[offset++] = ch;
if (ch == ENDCHAR) break;
}

... (free buffer)

Notably since we invoke getc() we could easily have more than one
termination character such as

if (ch == ''\n'' || ch == ''\0'' || ch == '','')

etc. which is intended to be a big advantage over calling a line
reader function.

--
James


James Harris wrote:

On 30 May, 14:12, James Harris <james.harri...@googlemail.comwrote:

>Initial issue: read in an arbitrary-length piece of text.
Perceived issue: handle variable-length data

The code below is a suggestion for implementing a variable length
buffer that could be used to read text or handle arrays of arbitrary
length. I don''t have the expertise in C of many folks here so I feel
like I''m offering a small furry animal for sacrifice to a big armour
plated one... but will offer it anyway. Please do suggest improvements
or challenge the premise. It would be great if it could be improved to
become a generally useful piece of code.

Well, here goes. This should be fun. :-?

-

The following utility code is passed a buffer (allocated by the
caller) and maintains it at an appropriate size. The main function
increases the allocation (when necessary) by factors - rather than
fixed amounts - for speed. There is a secondary function to trim a
buffer back to a specific size. An extra byte (one more than is
requested) is always left at the end.

/*
* Expanding buffer
*/

#define EBUF_SIZE_INIT 128
#define EBUF_SIZE_MIN 128
#define EBUF_INCREASE 1.5 /* Factor to increase space by each time */

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

Only a small, furry animal offering itself up for sacrifice
would use a non-standard header like <malloc.h>. Consider
yourself eaten by the Ravenous Bugblatter Beast.

Also, there seems to be no reason for <stdio.hin the
buffer-bashing code; it doesn''t hurt to #include extraneous
baggage, but it doesn''t help either. Everything you need
is in <stdlib.h>.

>int ebuf_full(char **buf, size_t *buf_size, size_t offset) {
size_t new_size;
char *new_buf;

if (*buf_size < offset + 2) { /* NB last pos left empty */

This magical `2'' appears in quite a few places. Maybe
it deserves a #define of its own?

> new_size = *buf_size * EBUF_INCREASE + 1;

As a small matter of personal preference and prejudice,
I myself would avoid floating-point arithmetic here and do
the calculation in integers. Not a big deal, though.

> if (new_size < offset + 2) new_size = offset + 2;
if (new_size < EBUF_SIZE_MIN) new_size = EBUF_SIZE_MIN;
if ((new_buf = realloc(*buf, new_size)) == NULL) {
return 1; /* Failed to realloc buffer */
}
*buf = new_buf;
*buf_size = new_size;
}
return 0; /* Reallocated successfuly */

}

int ebuf_trim(char **buf, size_t *buf_size, size_t offset) {
int new_size = offset + 2; /* Includes empty char */
char *new_buf;

if (new_size < EBUF_SIZE_MIN) new_size = EBUF_SIZE_MIN;
if (new_size != *buf_size) {
if ((new_buf = realloc(*buf, new_size)) == NULL) {
return 1; /* Reallocation failed (unlikely) */

There''s an interface design decision lurking here: Should
this be considered a "failure," or just an "unsuccessful
attempt to optimize?" Arguments can be made for both points
of view. IMHO you''ve chosen rightly, because it''s possible
that ebuf_trim() could fail in an attempt to *increase* the
size of the buffer, in which case the calling program might
be, er, surprised to discover that the buffer was too small
for the offset.

> }
*buf = new_buf;
*buf_size = new_size;
}
return 0; /* Reallocation succeeded */

}


An example of intended use follows. Note that the routines are coded
to expect buffer and current size as parameters. Despite the error
handling the code is intended to be fast. Including "if (offset + 2 >
buf1_size)" in the main code the function should only be called if the
buffer is too small. The cost of one integer comparison is small.

int main() {

`int main(void)'' would be very slightly better.

char *buf1;
size_t buf1_size = EBUF_SIZE_INIT;
size_t offset;

if ((buf1 = malloc(buf1_size)) == NULL) {
fprintf(stderr, "Buffer initial malloc of %d bytes failed\n",
buf1_size);

What is the type of buf1_size? Answer: size_t. What type
of operand does the "%d" specifier convert? Answer: int. Are
size_t and int the same? Answer: No. What should you do to
fix the mismatch? Answer: Change "%d" to "%g". (No, wait, I
didn''t mean that ...)

For fprintf() and so on, <stdio.h*is* needed.

exit(1);

ITYM `exit(EXIT_FAILURE);''. Or `return EXIT_FAILURE;''.

}

Instead of pre-allocating the initial buffer, why not
set buf1=NULL and buf1_size=0 and just let ebuf_full()
take care of everything?

...

offset = <position in buffer to write to>

...

/* Check buf1 is big enough */
if (offset + 2 buf1_size && ebuf_full(&buf1, &buf1_size, offset))
{
fprintf(stderr, "Buffer overflow - have %d bytes but need %d
bytes",
buf1_size, offset + 2);
exit(1);
}
buf1[offset] = 0;

...

free(buf1);

... and since main() returns an int value, you should ...?
(C99 introduced a special rule for main() that says falling
off the end is equivalent to returning zero, but IMHO this
should be viewed as a concession to the large amount of sloppy
code already in existence, not as an encouragement to further
sloppiness. Besides, C99 implementations have not exactly
taken the world by storm, and lots of C90 implementations are
still in use.)

}

It seems to me you understand the basic ideas of how to
use realloc() to grow a buffer (although the fact that you
can reallocate a NULL may have escaped you). There are a
few glitches in the way you''ve done things, easily fixable.

If you want to package something like this for wider
use as a buffer-managing utility, you might consider putting
the buffer information in a struct and passing a single
struct pointer to the functions. Not only would this make
the interface clearer by reducing the argument count, but
it would also make it easy for you to add further fillips
of functionality later on, just by adding a few elements
to the struct and leaving the calls alone.

Go back to your lair and lick your wounds; I think
they''re not life-threatening.

--
Er*********@sun.com


这篇关于扩展缓冲区 - 对“确定malloc的大小”的响应询问的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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