Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Dealing with struct padding using a dynamic element

Reply
Thread Tools

Dealing with struct padding using a dynamic element

 
 
mojumbo
Guest
Posts: n/a
 
      10-03-2008
Problem:

I have a structure which needs to store its data in contiguous memory
by there is a dynamic element which can't be defined at compile time.
It needs to be aligned along a 4 byte boundary. This is what my
structure looks like:

START

struct tsBob
{
unsigned int fieldA;
unsigned int fieldB;

unsigned short varLen[0];
}

tsBob* myBob;

myBob = (tsBob*)malloc(sizeof(tsBob) + sizeof(unsigned short) * 1);

END

myBob needs an additional 3 bytes alloc'd to it to be aligned. I
don't want to use %

Finally the question,

Can I use a bitwise something to determine how many extra bytes I need
and malloc that with the
rest of the function call?
 
Reply With Quote
 
 
 
 
Erik Wikström
Guest
Posts: n/a
 
      10-03-2008
On 2008-10-03 16:47, Victor Bazarov wrote:
> mojumbo wrote:
>> Problem:
>>
>> I have a structure which needs to store its data in contiguous memory
>> by there is a dynamic element which can't be defined at compile time.
>> It needs to be aligned along a 4 byte boundary. This is what my
>> structure looks like:


Unless you can use some kind of struct/type which is 4 bytes (and make
sure that the first element in the array is correctly aligned using
padding) instead of the unsigned shorts you will have to take care when
allocating the memory. Perhaps using a factory-function (which allocates
the correct number of bytes) would be a good idea.

>> struct tsBob
>> {
>> unsigned int fieldA;
>> unsigned int fieldB;
>>
>> unsigned short varLen[0];

>
> I am not sure this is OK, you might consider giving it at least 1 element.


It's not OK, the standard requires a number greater than zero, but some
compilers (gcc for one) accepts this. We use this a lot at work when
building messages to be sent over the network, and I find it helpful to
have the zero-sized array as a way of describing the message layout. It
usually looks something like this:

struct Msg
{
unsigned nrFoo;
unsigned nrBar;
#if 0
Foo foos[0];
Bar bars[0];
#endif
};

--
Erik Wikström
 
Reply With Quote
 
 
 
 
mojumbo
Guest
Posts: n/a
 
      10-03-2008
Thanks for the above comments but I will clarify:

I am using an overloaded operator new in the structure which takes the
number of elements just as you suggested, so the actual spec for the
struct does look like this.

struct tsBob
{
unsigned int fieldA;
unsigned int fieldB;

unsigned short varLen[0];

void* operator new(size_t, int aNum)
{ return malloc(sizeof(tsBob) + sizeof(unsigned short)*num; }
};

This is exactly what I'm trying to solve - aNum can come in as any
number (which is why I multiplied by one in my first explanation)

"bitwise something" meaning -
I also have another structure with float aFlts[0].
My new looks like this: void* operator new(size_t, int aNum) { return
sizeof(tsFltStr) + sizeof(float)* aNum + (aNum & 0x01) ? 1:0); }

It's nice with 32-bits, just add another.
Also, I thought zero length arrays were part of the C99 standard?
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      10-04-2008
On Oct 3, 4:47 pm, Victor Bazarov <(E-Mail Removed)> wrote:
> mojumbo wrote:
> > Problem:


> > I have a structure which needs to store its data in
> > contiguous memory by there is a dynamic element which can't
> > be defined at compile time. It needs to be aligned along a
> > 4 byte boundary. This is what my structure looks like:


> > START


> > struct tsBob
> > {
> > unsigned int fieldA;
> > unsigned int fieldB;


> > unsigned short varLen[0];


> I am not sure this is OK, you might consider giving it at
> least 1 element.


It's not legal C++. Nor legal C, but in C, the last element may
have an incomplete array type, e.g.:
unsigned short varLen[] ;
You can, of course, give the final element a length of 1 in
either language, but then any array access with an index greater
than 0 is undefined behavior.

> > }

> ;


> > tsBob* myBob;


> > myBob = (tsBob*)malloc(sizeof(tsBob) + sizeof(unsigned short) * 1);


> This is better accomplished by the correctly implemented
> 'operator new' in the class itself, and then you just do


> tsBob* myBob = new (true_varLen_count) myBob;


If alignment isn't an issue (and I don't think it can be in his
exact case), then this should be accompanied with:

struct tsBob
{
unsigned short* varLen()
{
return reinterpret_cast< unsigned short* >( this + 1 ) ;
}
} ;

or
struct tsBob
{
unsigned short& operator[]( std::size_t index ) ;
{
// bounds checking...
return reinterpret_cast< unsigned short* >(
this + 1)[ index ] ;
}
} ;

for accessing the additional elements. I'd also do something to
ensure that the actual length was correctly memorized somewhere.

> > END


> > myBob needs an additional 3 bytes alloc'd to it to be aligned. I
> > don't want to use %


> If the size in bytes is divisible by 4, it's going to be
> aligned on the 4 byte boundary. That's the specification of
> 'malloc', IIRC.


No. All that malloc (or operator new()) guarantee is that the
returned pointer is sufficiently aligned for any type. In his
case, he's safe because it's not conceivable that unsigned short
require more alignment than the unsigned int in his struct. In
general, however, you do have to worry about alignment; the
implementation of std::basic_string in g++ uses a similar trick,
and core dumps if you try to use std::basic_string< double > (or
probably std::basic_string< long long >). (Hmmm. I wonder if
there are any platforms where wchar_t is equivalent to a long
long. If so, g++ has a real problem.)

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique oriente objet/
Beratung in objektorientierter Datenverarbeitung
9 place Smard, 78210 St.-Cyr-l'cole, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
Hrvoje Prgea
Guest
Posts: n/a
 
      10-04-2008
James Kanze wrote:
>
> No. All that malloc (or operator new()) guarantee is that the
> returned pointer is sufficiently aligned for any type.


I knew about malloc, but are you sure this is true for operator new? It
should know the requirement of the needed type in advance so the largest
aligment seems like a overspecification?

-- Hrvoje Prgea
 
Reply With Quote
 
Maxim Yegorushkin
Guest
Posts: n/a
 
      10-04-2008
On 3 Oct, 22:25, Victor Bazarov <(E-Mail Removed)> wrote:
> mojumbo wrote:
> > [..]
> > Also, I thought zero length arrays were part of the C99 standard?

>
> They may have been, but what relevance does it have here? *We *are*
> talking C++ here, aren't we? *Not C99. *Or are you unaware that they are
> two different languages?


Was it not the original intent of C++ to be compatible with C?

--
Max
 
Reply With Quote
 
Hrvoje Prgea
Guest
Posts: n/a
 
      10-04-2008
Maxim Yegorushkin wrote:
>
> Was it not the original intent of C++ to be compatible with C?
>


It still is, but the c++ standard is always catching up with the c
standard. Unspecified/flexible length arrays are from C99, the latest
c++ standard is C++03 (which is an updated version of c++9. It'll
probably get in the new standard, sometime in the future.

For more about incompatibilities see:
http://david.tribble.com/text/cdiffs.htm#C99-fam
http://en.wikipedia.org/wiki/Compati..._C_and_C%2B%2B


 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      10-04-2008
Hrvoje Prgea wrote:
> James Kanze wrote:
>>
>> No. All that malloc (or operator new()) guarantee is that the
>> returned pointer is sufficiently aligned for any type.

>
> I knew about malloc, but are you sure this is true for operator new? It
> should know the requirement of the needed type in advance so the largest
> aligment seems like a overspecification?
>

No, operator new does not know which type is being allocated, it is only
passed the size.

--
Ian Collins.
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      10-06-2008
On Oct 4, 3:57 pm, Hrvoje Prge?a <(E-Mail Removed)> wrote:
> Maxim Yegorushkin wrote:


> > Was it not the original intent of C++ to be compatible with C?


Up to a certain point. The original C++ required function
prototypes, for example, which didn't even exist in C at the
time.

> It still is, but the c++ standard is always catching up with
> the c standard. Unspecified/flexible length arrays are from
> C99, the latest c++ standard is C++03 (which is an updated
> version of c++9. It'll probably get in the new standard,
> sometime in the future.


I don't think so. It would require at least a minimum of work
(a formal proposal, etc.), and no one thought it worth the
effort.

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique oriente objet/
Beratung in objektorientierter Datenverarbeitung
9 place Smard, 78210 St.-Cyr-l'cole, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      10-06-2008
On Oct 4, 3:20 pm, Hrvoje Prge?a <(E-Mail Removed)> wrote:
> James Kanze wrote:


> > No. All that malloc (or operator new()) guarantee is that the
> > returned pointer is sufficiently aligned for any type.


> I knew about malloc, but are you sure this is true for
> operator new? It should know the requirement of the needed
> type in advance so the largest aligment seems like a
> overspecification?


The operator new function doesn't know what type it is being
called for, and must return a pointer suitably aligned for any
function. (See 3.7.4.1.)

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique oriente objet/
Beratung in objektorientierter Datenverarbeitung
9 place Smard, 78210 St.-Cyr-l'cole, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Can *common* struct-members of 2 different struct-types, that are thesame for the first common members, be accessed via pointer cast to either struct-type? John Reye C Programming 28 05-08-2012 12:24 AM
struct memory padding simonp@nospam.com C++ 11 01-22-2007 10:56 PM
Padding bits and struct assignment Hallvard B Furuseth C Programming 5 12-27-2006 10:19 PM
struct padding edware C Programming 9 04-27-2006 12:40 AM
struct my_struct *p = (struct my_struct *)malloc(sizeof(struct my_struct)); Chris Fogelklou C Programming 36 04-20-2004 08:27 AM



Advertisments