473,811 Members | 2,770 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Dynamic buffer library


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.
Aug 30 '06 #1
26 3489
Andrew Poelstra wrote:
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 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 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 ?
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
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 ?

Aug 30 '06 #2
Spiros Bousbouras wrote:
Andrew Poelstra wrote:

It compiles in gcc with all warnings set.
From the code it seems that your intention is to store
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 ?
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.

Aug 30 '06 #3
"Spiros Bousbouras" <sp****@gmail.c omwrites:
>>From the code it seems that your intention is to store
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 ?
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.
Aug 30 '06 #4
Spiros Bousbouras wrote:
Spiros Bousbouras wrote:
.... snip ...
>>
>From the code it seems that your intention is to store
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 ?

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.
Now this is one area where Google is NOT broken. A blank line,
followed by the word 'From', signals the start of a mail/news
message. Adding the '>' prevents that, and will be done by all
good newsreaders.

Just get yourself a proper newsreader. Thunderbird comes to mind.

--
Some informative links:
news:news.annou nce.newusers
http://www.geocities.com/nnqweb/
http://www.catb.org/~esr/faqs/smart-questions.html
http://www.caliburn.nl/topposting.html
http://www.netmeister.org/news/learn2quote.html

Aug 31 '06 #5
On Wed, 30 Aug 2006 21:48:37 GMT, Andrew Poelstra
<ap*******@fals e.sitewrote:
>
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]))
You forgot the 3*sizeof(size_t ) in the second parameter to realloc. If
create_buffer is called with a small value of max, your realloc could
actually reduce the amount of allocated space.

After you have reallocated the space, how does your caller know where
it is?
--max;
}

/* If we now have enough space, we're good. Otherwise, we're cooked. */
if (max num) {
memmove (buf, itm, size);
If you reallocated the space, buf need not be a valid address.
return num;
} else return 0;
}
/* End. */

It compiles in gcc with all warnings set.
Syntax is only one of many contributors to effectiveness. Necessary
but not sufficient.
Remove del for email
Aug 31 '06 #6
Andrew Poelstra schrieb:
"Spiros Bousbouras" <sp****@gmail.c omwrites:
>>>From the code it seems that your intention is to store
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 ?

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?
There is no portable way that does all the work; some time ago,
I wrote a "memsize" solution that does store the size in a standard
conforming albeit ugly and wasteful way. I asked for a code review
back then but did not receive any response; you are welcome to take
out the useful part of the ideas:
<36************ *@individual.ne t>
Download seems still possible.
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Aug 31 '06 #7
Michael Mair <Mi**********@i nvalid.invalidw rites:
Andrew Poelstra schrieb:
>"Spiros Bousbouras" <sp****@gmail.c omwrites:
>>>>From the code it seems that your intention is to store
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 ?

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?

There is no portable way that does all the work; some time ago,
I wrote a "memsize" solution that does store the size in a standard
conforming albeit ugly and wasteful way. I asked for a code review
back then but did not receive any response; you are welcome to take
out the useful part of the ideas:
<36************ *@individual.ne t>
Download seems still possible.
Thanks! That'll be useful, and probably end up being my solution.
A quick question, though, is struct padding consistant?

That is, for every struct { int x, size_t y, float z }, will (&z - &x)
always be the same number? Because if so, a more efficient solution
could be found.

--
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.
Aug 31 '06 #8
Andrew Poelstra schrieb:
Michael Mair <Mi**********@i nvalid.invalidw rites:
>>Andrew Poelstra schrieb:
>>>"Spiros Bousbouras" <sp****@gmail.c omwrites:
>From the code it seems that your intention is to store
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 ?

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?

There is no portable way that does all the work; some time ago,
I wrote a "memsize" solution that does store the size in a standard
conforming albeit ugly and wasteful way. I asked for a code review
back then but did not receive any response; you are welcome to take
out the useful part of the ideas:
<36************ *@individual.ne t>
Download seems still possible.

Thanks! That'll be useful, and probably end up being my solution.

A quick question, though, is struct padding consistant?

That is, for every struct { int x, size_t y, float z }, will (&z - &x)
always be the same number? Because if so, a more efficient solution
could be found.
If you always use the same identifiers for members of structs
with this layout and this sequence of types in your source: Yes
(see "compatible type" in the standard).
If not: The standard does not guarantee it but in every
implementation worth its salt, yes.
Read the bits about compatible types w.r.t. structure types and
about the "common initial sequence" for unions in the standard
to get a feeling about what is guaranteed (C90 or C99).
The DS900x series probably uses a member name based struct layout
for struct types not used in a union...

Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Aug 31 '06 #9
Michael Mair wrote:
Andrew Poelstra schrieb:
"Spiros Bousbouras" <sp****@gmail.c omwrites:
>>From the code it seems that your intention is to store
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 ?
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?

There is no portable way that does all the work; some time ago,
I wrote a "memsize" solution that does store the size in a standard
conforming albeit ugly and wasteful way. I asked for a code review
back then but did not receive any response; you are welcome to take
out the useful part of the ideas:
<36************ *@individual.ne t>
Download seems still possible.
This may be interesting as an academic exercise but
personally I don't see the point of storing the size of
the buffer in the buffer. Whoever needs to use the buffer
will need to know the location of it so if they can remember
the location then why not also the size ?

The way I'd do it would be to have a structure
struct buffer{size_t size ; size_t max ; size_t num ;
void * beg_of_bf ;}
and pass pointers to buffer to the functions
create_buffer and append_item

In the case of create_buffer the caller would
initialize fields size and max and the function
the fields num (set to 0) and beg_of_bf

In the case of append_item the return value
will determine if the appending was done
succesfully and if yes it will update num and
possibly also max and beg_of_bf if reallocation
was required.

Sep 1 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
1568
by: Shailesh | last post by:
If I'm not mistaken, C++ doesn't have support for dynamic class members. I'm considering if such a facility would be useful, and what method would make a good workaround. I have a generic buffer class, which can have one or more cursor classes attached to it. Right now, they are both separate classes, and I use them as follows: class Buffer { ...
4
7706
by: Scott Lyons | last post by:
Hey all, Can someone help me figure out how to pass a dynamic array into a function? Its been giving me some trouble, and my textbook of course doesnt cover the issue. Its probably something simple, but its just not popping into my mind at the moment. My little snippet of code is below. Basically, the studentID array is dynamic so it will fit any length of a Student's Name. What I'm trying to do is place this chunk of code into a...
5
3765
by: swarsa | last post by:
Hi All, I realize this is not a Palm OS development forum, however, even though my question is about a Palm C program I'm writing, I believe the topics are relevant here. This is because I believe the problem centers around my handling of strings, arrays, pointers and dynamic memory allocation. Here is the problem I'm trying to solve: I want to fill a list box with a list of Project Names from a database (in Palm this is more...
27
3246
by: lovecreatesbea... | last post by:
This code snippet is an exercise on allocating two dimension array dynamically. Though this one is trivial, is it a correct one? Furthermore, when I tried to make these changes to the original example: for (i = 0; i < ROW + 2; ++i){ /*line 14*/ strcpy(array, "C! C!"); /*line 15*/ Apparently, the modified code wrote to the memory unit outside the allocated array, but the program ran well and there was no Segmentation
13
2043
by: coosa | last post by:
Dear all, Using the conio implementation i wanted to create a dynamic string, whereby its size would be determined after each keyboard hit; in other words, i don't want to ask the user to specify the the size, but rather keep him/her typing and after each keyboard hit, the function getch() determines whether he/she entered the ENTER key to end the process; otherwise, increases the dynamic size or also decreases it if the back key was...
0
1424
by: vinbelgian | last post by:
I have some trouble with making a buffer in vb.net. I use a C dll that requires me to give him a pointer to a buffer of bytes where he is going to write bytes to, depending on the command i give. the import of the dll: with the C procedures in comments ' declarations for integration test.dll ' int __stdcall test_Open(char *device, long to); <DllImport("test.dll")Private Shared Function test_Open(ByVal
0
1641
by: padhuwork | last post by:
Hi, I want to create a Windows DLL using VC++ 6.0 which connects to SQL Server. After establishing the connection, I want to retrieve records from table (query) and out put the recordset to a text file. Can you any expert, give me ideas as to how to go about? I have used the following code for connection and connection is successful. I m able to insert records (i got the code from codeproject website). I was successfully able to insert...
1
9069
by: pete m | last post by:
I would like to support stdio functions for an extremely primitive type system, as shown in the attached sample program, using dynamic creation of a va_list. I've tested it on successfully a couple platforms, but what I don't know is whether it's actually a legal program. The function of interest is usnprintf, "union sprintf". (psnprintf is a dummy wrapper for vsnprintf, useful for debugging.)
6
3886
by: Richard Gilmore | last post by:
Ok I need to create a dynamic array of pointers to strings, the number of strings is determined by the typed value at the keyboard, and then the length of each string is determined as it's typed in char **zerg; char ch; int num; int i; char buffer; printf("Enter the number of names you wish to store>"); scanf("%d",&num); zerg = (char **)malloc(num);
0
9731
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9605
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10393
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10405
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10136
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7671
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6893
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5556
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
3
3020
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.