动态缓冲库 [英] Dynamic buffer library

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

问题描述



我今天早上一起攻击了这个,这样我就可以将我的超出
空格代码从其余的逻辑中移开。我想在我的动态缓冲区上允许数组

语法,所以我手动创建了一个带有

malloc()的结构,并明智地使用了void *指针。


我决定发布它,因为这样的东西是

UB的滋生地,而这个小组很擅长找到它。 (我有一个牙医类比

,但它没有用完。)


这是我的代码:


/ *开始。 * /

#include< stdlib.h>

#include< string.h>


void * create_buffer( size_t size,size_t max)

{

/ *我们需要在实际缓冲区之前分配三个size_t来保存

*每个的大小item,最大项目数和实际

*项目数。我们这样做而不是使用结构,因此仍然可以在返回的结构上使用

*数组语法。 * /

size_t * tmp = malloc((3 * sizeof * tmp)+(size * max));


if(tmp!= NULL)

{

tmp [0] =大小; / *每件商品的尺寸* /

tmp [1] = max; / *最大项目数* /

tmp [2] = 0; / *实际项目数* /

}


return(tmp!= NULL)? tmp + 3:NULL;

}


/ *这个函数会返回三个可能的东西:

* 1.普通用法,它将返回缓冲区的新的最大大小。

* 2.如果内存不足,它将返回0.

* 3.如果传递NULL ,它只会返回buf的最大大小。

*在第二种情况之后使用第三种情况来恢复丢失的大小信息。

*如果buf为NULL,坏事会发生。 * /

size_t append_item(void * buf,void * itm)

{

size_t * tmp =(size_t *)buf - 3;

size_t size = tmp [0];

size_t max = tmp [1];

size_t num = ++ tmp [2];


/ *特殊情况下的早期退货。 * /

if(itm == NULL)

返回num;


/ *如果我们没有足够的空间,尝试并获得更多。 * /

if(num == max){

size_t * rtmp;

max * = 2;

while(!(rtmp = realloc(tmp,max))&&(max tmp [1]))

--max;

}


/ *如果我们现在有足够的空间,我们很好。否则,我们煮熟了。 * /

if(max num){

memmove(buf,itm,size);

返回num;

}否则返回0;

}

/ *结束。 * /


它在gcc中编译并设置了所有警告。


-

Andrew Poelstra< http ://www.wpsoftware.net/projects>

要通过电子邮件与我联系,请在上述域名中使用apoelstra。

" Do BOTH结束了电缆需要插上电源吗? -Anon。


I hacked this together this morning so that I could shift my out-of-
space code away from the rest of my logic. I wanted to allow array
syntax on my dynamic buffers, so I manually created a struct with
malloc() and judicious use of void* pointers.

I decided to post it because stuff like this is breeding ground for
UB, and this group is good at finding it. (I had a dentist analogy
for that, but it didn''t work out.)

Here''s my code:

/* Start. */
#include <stdlib.h>
#include <string.h>

void *create_buffer (size_t size, size_t max)
{
/* We need to allocate three size_t before the actual buffer to hold
* the size of each item, the maximum number of items, and the actual
* number of items. We do it this way instead of using a struct so that
* array syntax can still be used on the returned structure. */
size_t *tmp = malloc ( (3 * sizeof *tmp) + (size * max) );

if (tmp != NULL)
{
tmp[0] = size; /* Size of each item */
tmp[1] = max; /* Maximum # of items */
tmp[2] = 0; /* Actual # of items */
}

return (tmp != NULL) ? tmp + 3 : NULL;
}

/* This function will return three possible things:
* 1. On ordinary usage, it will return the new maximum size of the buffer.
* 2. If it runs out of memory, it will return 0.
* 3. If passed NULL, it will do nothing but return maximum size of buf.
* The third case is used after the second case to recover lost size info.
* If buf is NULL, Bad Things will happen. */
size_t append_item (void *buf, void *itm)
{
size_t *tmp = (size_t *) buf - 3;
size_t size = tmp[0];
size_t max = tmp[1];
size_t num = ++tmp[2];

/* Early return on special case. */
if (itm == NULL)
return num;

/* If we don''t have enough space, try and get some more. */
if (num == max) {
size_t *rtmp;
max *= 2;
while (!(rtmp = realloc (tmp, max)) && (max tmp[1]))
--max;
}

/* If we now have enough space, we''re good. Otherwise, we''re cooked. */
if (max num) {
memmove (buf, itm, size);
return num;
} else return 0;
}
/* End. */

It compiles in gcc with all warnings set.

--
Andrew Poelstra <http://www.wpsoftware.net/projects>
To reach me by email, use `apoelstra'' at the above domain.
"Do BOTH ends of the cable need to be plugged in?" -Anon.

推荐答案

Andrew Poelstra写道:
Andrew Poelstra wrote:

我今天早上一起入侵了这个这样我就可以将我的超出
空间代码从其余的逻辑中移开。我想在我的动态缓冲区上允许数组

语法,所以我手动创建了一个带有

malloc()的结构,并明智地使用了void *指针。


我决定发布它,因为这样的东西是

UB的滋生地,而这个小组很擅长找到它。 (我有一个牙医类比

,但它没有用完。)


这是我的代码:


/ *开始。 * /

#include< stdlib.h>

#include< string.h>


void * create_buffer( size_t size,size_t max)

{

/ *我们需要在实际缓冲区之前分配三个size_t来保存

*每个的大小item,最大项目数和实际

*项目数。我们这样做而不是使用结构,因此仍然可以在返回的结构上使用

*数组语法。 * /

size_t * tmp = malloc((3 * sizeof * tmp)+(size * max));


if(tmp!= NULL)

{

tmp [0] =大小; / *每件商品的尺寸* /

tmp [1] = max; / *最大项目数* /

tmp [2] = 0; / *实际项目数* /

}


return(tmp!= NULL)? tmp + 3:NULL;

}


/ *这个函数会返回三个可能的东西:

* 1.普通用法,它将返回缓冲区的新的最大大小。

* 2.如果内存不足,它将返回0.

* 3.如果传递NULL ,它只会返回buf的最大大小。

*在第二种情况之后使用第三种情况来恢复丢失的大小信息。

*如果buf为NULL,坏事会发生。 * /

size_t append_item(void * buf,void * itm)

{

size_t * tmp =(size_t *)buf - 3;

size_t size = tmp [0];

size_t max = tmp [1];

size_t num = ++ tmp [2];


/ *特殊情况下的早期退货。 * /

如果(itm == NULL)

返回num;
I hacked this together this morning so that I could shift my out-of-
space code away from the rest of my logic. I wanted to allow array
syntax on my dynamic buffers, so I manually created a struct with
malloc() and judicious use of void* pointers.

I decided to post it because stuff like this is breeding ground for
UB, and this group is good at finding it. (I had a dentist analogy
for that, but it didn''t work out.)

Here''s my code:

/* Start. */
#include <stdlib.h>
#include <string.h>

void *create_buffer (size_t size, size_t max)
{
/* We need to allocate three size_t before the actual buffer to hold
* the size of each item, the maximum number of items, and the actual
* number of items. We do it this way instead of using a struct so that
* array syntax can still be used on the returned structure. */
size_t *tmp = malloc ( (3 * sizeof *tmp) + (size * max) );

if (tmp != NULL)
{
tmp[0] = size; /* Size of each item */
tmp[1] = max; /* Maximum # of items */
tmp[2] = 0; /* Actual # of items */
}

return (tmp != NULL) ? tmp + 3 : NULL;
}

/* This function will return three possible things:
* 1. On ordinary usage, it will return the new maximum size of the buffer.
* 2. If it runs out of memory, it will return 0.
* 3. If passed NULL, it will do nothing but return maximum size of buf.
* The third case is used after the second case to recover lost size info.
* If buf is NULL, Bad Things will happen. */
size_t append_item (void *buf, void *itm)
{
size_t *tmp = (size_t *) buf - 3;
size_t size = tmp[0];
size_t max = tmp[1];
size_t num = ++tmp[2];

/* Early return on special case. */
if (itm == NULL)
return num;



这不会返回缓冲区的最大大小。

This doesn''t return the maximum size of buffer.


>

/ *如果我们没有足够的空间,请尝试获得更多。 * /

if(num == max){

size_t * rtmp;

max * = 2;

while(!(rtmp = realloc(tmp,max))&&(max tmp [1]))

--max;

}


/ *如果我们现在有足够的空间,我们很好。否则,我们煮熟了。 * /

if(max num){

memmove(buf,itm,size);
>
/* If we don''t have enough space, try and get some more. */
if (num == max) {
size_t *rtmp;
max *= 2;
while (!(rtmp = realloc (tmp, max)) && (max tmp[1]))
--max;
}

/* If we now have enough space, we''re good. Otherwise, we''re cooked. */
if (max num) {
memmove (buf, itm, size);



buf仍然指向旧的内存块。

无论如何你想要新项目

放在现有的之后,对吗?

buf still points to the old memory block.
And in any case you want the new item to
be placed after the already existing ones , right ?


返回num;

}否则返回0;

}

/ *结束。 * /


它在gcc中编译并设置了所有警告。
return num;
} else return 0;
}
/* End. */

It compiles in gcc with all warnings set.


>从代码中看来你的意图是存储
>From the code it seems that your intention is to store



"项目"从buf开始[3]。是物品类型

size_t?如果不是,你怎么知道buf [3]是否正确

对齐?

the "items" starting at buf[3]. Are the items of type
size_t ? If not how do you know that buf[3] is properly
aligned ?


Spiros Bousbouras写道:
Spiros Bousbouras wrote:

Andrew Poelstra写道:
Andrew Poelstra wrote:


它在gcc中编译并设置了所有警告。

It compiles in gcc with all warnings set.


从代码中看来,您的意图似乎是存储
From the code it seems that your intention is to store



项"从buf开始[3]。是物品类型

size_t?如果不是,你怎么知道buf [3]是否正确

对齐?

the "items" starting at buf[3]. Are the items of type
size_t ? If not how do you know that buf[3] is properly
aligned ?



好​​吧,谷歌的界面确实破了。行阅读

从代码中看来,你的意图是存储是由我写的

但Google在From之前添加了一个权利。 !

它认为这是一个邮件文件!


我现在开始寻找不同的基于网络的界面

to usenet。

Ok , Google''s interface is indeed broken. The line reading
"From the code it seems that your intention is to store" was
written by me but Google added a right before "From" !
It thinks it''s a mail file !

I''ll now start searching for a different web based interface
to usenet.


" Spiros Bousbouras" < sp **** @ gmail.comwrites:
"Spiros Bousbouras" <sp****@gmail.comwrites:

>>从代码中看来你的意图似乎是商店
>>From the code it seems that your intention is to store



" items"从buf开始[3]。是物品类型

size_t?如果不是,你怎么知道buf [3]是否正确

对齐?

the "items" starting at buf[3]. Are the items of type
size_t ? If not how do you know that buf[3] is properly
aligned ?



这些项目可能不是size_t。我不知道他们是否正确对齐(这是UB的一个例子,我知道我错过了)。什么

对我来说是保证对齐的最佳方式?我要去

需要使用工会吗?


感谢您的评论:我已经更正了我的append_item功能

下面(大部分只是拼写错误和错过的行):


/ *我们现在需要获取缓冲区的地址,因为realloc()

*可能会改变指针的值。 * /

size_t append_item(void ** buf,void * itm)

{

size_t * tmp =(size_t *)* buf - 3;

size_t size = tmp [0];

size_t max = tmp [1];

size_t num = ++ tmp [2 ];


/ *特殊情况的早期回报。 * /

if(itm == NULL)

返回最大值;


/ *如果我们没有足够的空间,尝试并获得更多。 * /

if(num == max){

size_t * rtmp;

max * = 2;

rtmp = realloc(tmp,max);

while((rtmp == NULL)&&(max tmp [1]))

rtmp = realloc(tmp, - max);

}


/ *如果我们现在有足够的空间,我们很好。否则,我们煮熟了。 * /

if(max num){

* buf = rtmp;

memmove(buf,itm,size);

返回num;

}否则返回0;

}


-

Andrew Poelstra< http://www.wpsoftware.net/projects>

要通过电子邮件与我联系,请在上述域名中使用apoelstra。

" ;是否需要插入电缆的两端? -Anon。

The items may not be of size_t. I don''t know that they''re properly
aligned (this is an example of the UB I knew that I missed). What
would be the best way for me to guarantee alignment? Am I going to
need to use a union?

Thanks for your comments: I''ve corrected my append_item function
below (most of it was just typos and missed lines):

/* We now need to get the address of the buffer, because realloc()
* may change the value of the pointer. */
size_t append_item (void **buf, void *itm)
{
size_t *tmp = (size_t *) *buf - 3;
size_t size = tmp[0];
size_t max = tmp[1];
size_t num = ++tmp[2];

/* Early return on special case. */
if (itm == NULL)
return max;

/* If we don''t have enough space, try and get some more. */
if (num == max) {
size_t *rtmp;
max *= 2;

rtmp = realloc (tmp, max);
while ((rtmp == NULL) && (max tmp[1]))
rtmp = realloc (tmp, --max);
}

/* If we now have enough space, we''re good. Otherwise, we''re cooked. */
if (max num) {
*buf = rtmp;
memmove (buf, itm, size);
return num;
} else return 0;
}

--
Andrew Poelstra <http://www.wpsoftware.net/projects>
To reach me by email, use `apoelstra'' at the above domain.
"Do BOTH ends of the cable need to be plugged in?" -Anon.


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

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