473,608 Members | 1,809 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

alignment when allocating an array of struct

Hello, I'm asking myself all kind of questions on allocating
an array of struct with proper alignment.

Is the following code oorrect ?

I'm most interested by the statement
t = malloc(n*sizeof (r))
and (to a degree) by the surrounding error checking.
#include <stdlib.h>

// a record of system-dependent size and alignment
typedef struct r
{
char f0;
long f1;
char f2;
} r;

int main(int argc, char *argv[])
{
long n; // number of elements to allocate
r *t; // array of n records of type r
if (argc==2 && // check argv[1] is our single parameter
(n = atol(argv[1]))>0 && // convert to a positive number
(size_t)(n*size of(r))/n==sizeof(r) && // check for size overflow
// allocate n records of type r; is that OK ?
(t = malloc(n*sizeof (r)))!=NULL)
{
// some use the array of n records
long j;
for(j=0;j<n;++j )
t[j].f1 = j; // use a (conseivably) aligned field
free(t);
}
return 0;
}
On systems where alignment must occur for proper acess to
the field f1, is sizeof(r) guaranteed to be rounded up
appropriately, and/or malloc guaranteed to return approriately
aligned memory ?

Is the calloc() library function guaranteed to perform something
extra (beside zeroing the allocated memory) ? like, perhaps,
rounding up the size passed, or checking that the product does
not overflow, or making extra alignment ?

As an aside: one of my C compilers barks if I change sizeof(r)
to sizeof r. Is this compiler defective ? No it is NOT C++.
TIA,

Francois Grieu
Jan 4 '08 #1
6 5168
Francois Grieu wrote:
Hello, I'm asking myself all kind of questions on allocating
an array of struct with proper alignment.

Is the following code oorrect ?

I'm most interested by the statement
t = malloc(n*sizeof (r))
and (to a degree) by the surrounding error checking.
#include <stdlib.h>

// a record of system-dependent size and alignment
typedef struct r
{
char f0;
long f1;
char f2;
} r;

int main(int argc, char *argv[])
{
long n; // number of elements to allocate
r *t; // array of n records of type r
if (argc==2 && // check argv[1] is our single parameter
(n = atol(argv[1]))>0 && // convert to a positive number
(size_t)(n*size of(r))/n==sizeof(r) && // check for size overflow
// allocate n records of type r; is that OK ?
(t = malloc(n*sizeof (r)))!=NULL)
{
// some use the array of n records
long j;
for(j=0;j<n;++j )
t[j].f1 = j; // use a (conseivably) aligned field
free(t);
}
return 0;
}
On systems where alignment must occur for proper acess to
the field f1, is sizeof(r) guaranteed to be rounded up
appropriately, and/or malloc guaranteed to return approriately
aligned memory ?
Yes and yes. For the first, consider an array `r array[2];'.
Both array[0] and array[1] must be properly aligned, and the
sizeof the array is twice the size of one of its elements, that
is, twice the sizeof(r). So sizeof(r) must include whatever
padding might be needed to make the alignment work properly.
It's not a matter of rounding up the result of sizeof; it's that
the r instance contains its own padding and the padding counts
as part of the sizeof an r.

For the second, the Standard requires that malloc() return
memory that is suitably aligned for *any* type whatsoever. In
particular, this means that the memory is suitably aligned for
an r.
Is the calloc() library function guaranteed to perform something
extra (beside zeroing the allocated memory) ? like, perhaps,
rounding up the size passed, or checking that the product does
not overflow, or making extra alignment ?
As with malloc(), no "rounding up" is needed because any
padding is already accounted for in the sizeof the type. And
as with malloc(), the returned memory must be suitably aligned
for any type at all, including the type r.

As for overflow, I believe a proper calloc() implementation
must detect it and return NULL rather than being oblivious to
it and possibly returning a pointer to a too-small area. The
Standard says that calloc() either allocates enough space for
the implied array or fails to allocate it, and leaves no room
for a calloc() that "sort of" works. However, I'm not 100% sure
that my reading is correct -- and I'm even *less* sure that all
calloc() implementations perform the detection I think is required.
As an aside: one of my C compilers barks if I change sizeof(r)
to sizeof r. Is this compiler defective ? No it is NOT C++.
The compiler is right. r is a type name (an alias for a
type name, actually), so writing `sizeof r' is like writing
`sizeof int' -- and is equally wrong.

--
Er*********@sun .com
Jan 4 '08 #2
Francois Grieu wrote:
On 4 jan, 19:32, Eric Sosman <Eric.Sos...@su n.comwrote:
>sizeof(r) must include whatever padding might be needed to make
the alignment work properly.
It's not a matter of rounding up the result of sizeof; it's that
the r instance contains its own padding and the padding counts
as part of the sizeof an r.

Ah... sizeof(r) itself is already properly rounded up. That's fine,
and clears most of my concerns. But, just to be sure, how is that
expressed in the (C89/90) standard ?
I don't have either the original ANSI nor the first ISO
version of the Standard handy, so I don't know. In N2794 (a
pre-C99 draft; I've lost a disk and haven't retrieved my
backup of the actual Standard yet), 6.5.3.4p3 says in part

[...] When applied to an operand that has structure or
union type, the result is the total number of bytes in
such an object, including internal and trailing padding.
Is there something wrong with my overflow test ?
(size_t)(n*size of(r))/n==sizeof(r)
Anything less contorted ?
Since `n' is a signed long, this risks overflow with
undefined behavior on machines where size_t promotes to
long instead of the other way around. Try converting to
size_t before multiplying, so the arithmetic is unsigned
and "overflow" is well-behaved:

((size_t)n * sizeof(r)) / sizeof(r) == n

This particular rearrangement works even when n==0, and
it also catches negative n when size_t promotes to long.
I think that it also catches negative n when long promotes
to size_t, provided sizeof(r)>1. (Besides, dividing by
a compile-time constant is likely to be faster than by a
variable; just THINK of the nanoseconds you'll save! ;-)

--
Er*********@sun .com
Jan 4 '08 #3
Francois Grieu <fg****@gmail.c omwrites:
On 4 jan, 19:32, Eric Sosman <Eric.Sos...@su n.comwrote:
[...]
> The compiler is right. r is a type name (an alias for a
type name, actually), so writing `sizeof r' is like writing
`sizeof int' -- and is equally wrong.

Got it: sizeof variable is fine, sizeof type is wrong.
Thanks for everything.
Right. More generally, there are two forms of size expression:

sizeof unary-expression
sizeof ( type-name )

The unary-expression may be a variable name, but it doesn't have to
be. For example, ``sizeof 42'' is equivalent to ``sizeof int''.

(The use of "unary-expression" rather than "expression " means that,
for example, ``sizeof 2 + 2'' doesn't apply the sizeof operator to
``2 + 2''; instead, it means ``(sizeof 2) + 2''. It's a way of
expressing operator precedence.)

--
Keith Thompson (The_Other_Keit h) <ks***@mib.or g>
[...]
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jan 5 '08 #4
In article <1199487009.440 461@news1nwk>,
Eric Sosman <Er*********@su n.comwrote:
Francois Grieu wrote:
>On 4 jan, 19:32, Eric Sosman <Eric.Sos...@su n.comwrote:
>>sizeof(r) must include whatever padding might be needed to make
the alignment work properly.
It's not a matter of rounding up the result of sizeof; it's that
the r instance contains its own padding and the padding counts
as part of the sizeof an r.

Ah... sizeof(r) itself is already properly rounded up. That's fine,
and clears most of my concerns. But, just to be sure, how is that
expressed in the (C89/90) standard ?

I don't have either the original ANSI nor the first ISO
version of the Standard handy, so I don't know. In N2794 (a
pre-C99 draft; I've lost a disk and haven't retrieved my
backup of the actual Standard yet), 6.5.3.4p3 says in part

[...] When applied to an operand that has structure or
union type, the result is the total number of bytes in
such an object, including internal and trailing padding.
I confirm this is also in ISO/IEC 9899:1999.

>Is there something wrong with my overflow test ?
(size_t)(n*size of(r))/n==sizeof(r)
Anything less contorted ?

Since `n' is a signed long, this risks overflow with
undefined behavior on machines where size_t promotes to
long instead of the other way around. Try converting to
size_t before multiplying, so the arithmetic is unsigned
and "overflow" is well-behaved:

((size_t)n * sizeof(r)) / sizeof(r) == n

This particular rearrangement works even when n==0, and
it also catches negative n when size_t promotes to long.
I think that it also catches negative n when long promotes
to size_t, provided sizeof(r)>1. (Besides, dividing by
a compile-time constant is likely to be faster than by a
variable; just THINK of the nanoseconds you'll save! ;-)
Took me an iteration to realize that this works even if
size_t is much smaller than long. Thanks!
Francois Grieu
Jan 7 '08 #5
On Fri, 04 Jan 2008 18:50:05 +0100, Francois Grieu <fg****@gmail.c om>
wrote:
>Hello, I'm asking myself all kind of questions on allocating
an array of struct with proper alignment.

Is the following code oorrect ?

I'm most interested by the statement
t = malloc(n*sizeof (r))
and (to a degree) by the surrounding error checking.
#include <stdlib.h>

// a record of system-dependent size and alignment
typedef struct r
{
char f0;
long f1;
char f2;
} r;

int main(int argc, char *argv[])
{
long n; // number of elements to allocate
r *t; // array of n records of type r
if (argc==2 && // check argv[1] is our single parameter
(n = atol(argv[1]))>0 && // convert to a positive number
atol is not a very good function for this purpose. Better to use
strtol and take advantage of its error checking capabilities prior to
using the result in the if.
(size_t)(n*size of(r))/n==sizeof(r) && // check for size overflow
What is the type of the product of a long and a size_t. Not just on
your system but in general. If size_t is an unsigned int, I think the
result would be a long and overflow could occur. Better to eliminate
the possibility and move the cast inside the parentheses to get
((size_t)n*size of(r))

Even better still would be to change n to a size_t and use strtoul
instead of strtol or atol above.
// allocate n records of type r; is that OK ?
(t = malloc(n*sizeof (r)))!=NULL)
1 - Your parentheses are unbalanced. You are missing a ).

2 - Wouldn't you like to be able to put out a different error message
depending on whether argc was not 2 or malloc failed or ...?

While the short-circuit mechanism inherent in && can make this complex
if logically correct, it is a maintenance nightmare.
{
// some use the array of n records
long j;
for(j=0;j<n;++j )
t[j].f1 = j; // use a (conseivably) aligned field
Under what conditions would you expect an array element or struct
member to not be aligned?
free(t);
}
return 0;
}
On systems where alignment must occur for proper acess to
the field f1, is sizeof(r) guaranteed to be rounded up
Consider the havoc it would cause if you defined a simple array of
struct and the size was not rounded up as needed. Yes it is
guaranteed.
>appropriatel y, and/or malloc guaranteed to return approriately
aligned memory ?
malloc and friends are also guaranteed to return an address properly
aligned for any and every possible type of object, scalar or
aggregate.
>
Is the calloc() library function guaranteed to perform something
extra (beside zeroing the allocated memory) ? like, perhaps,
rounding up the size passed, or checking that the product does
On what basis would it round up more than the product? It has no idea
what type of pointer you are assigning the resulting address to.
>not overflow, or making extra alignment ?
Since the alignment is guaranteed to be suitable for any type of
object, what possible extra alignment is there?

Since calloc allocates space for an array and size_t can hold the size
of the largest possible array, I suggest that consistency demands that
passing parameters to calloc where the product would exceed SIZE_MAX
invokes undefined behavior
>
As an aside: one of my C compilers barks if I change sizeof(r)
to sizeof r. Is this compiler defective ? No it is NOT C++.
The parentheses are required unless the operand is an object. r is
not an object. It is a typedef alias for struct r and both
expressions are types, not objects. You could use *t with or without
parentheses since *t is an object of type r. Any of your compilers
that do not bark on sizeof r are broken.
Remove del for email
Jan 8 '08 #6
Barry Schwarz <sc******@doezl .netwrites:
On Fri, 04 Jan 2008 18:50:05 +0100, Francois Grieu <fg****@gmail.c om>
wrote:
[...]
>>As an aside: one of my C compilers barks if I change sizeof(r)
to sizeof r. Is this compiler defective ? No it is NOT C++.

The parentheses are required unless the operand is an object. r is
not an object. It is a typedef alias for struct r and both
expressions are types, not objects. You could use *t with or without
parentheses since *t is an object of type r. Any of your compilers
that do not bark on sizeof r are broken.
Correction: the parentheses are required unless the operand is an
expression. For example ``sizeof 42'' is valid.

The operand of a sizeof operator is either an expression (specifically
a "unary-expression") or a type name in parentheses.

--
Keith Thompson (The_Other_Keit h) <ks***@mib.or g>
[...]
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jan 8 '08 #7

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

Similar topics

2
3012
by: derek.google | last post by:
I have an application that's crashing because of an alignment problem, and this is the smallest program that demonstrates what's happening: int main() { struct Message { unsigned short size; }; const int START_INDEX = 1; char* buffer = new char; Message* msg = (Message*)&buffer;
36
7747
by: Bhalchandra Thatte | last post by:
I am allocating a block of memory using malloc. I want to use it to store a "header" structure followed by structs in my application. How to calculate the alignment without making any assumption about the most restrictive type on my machine? Thanks.
4
17680
by: Shashi | last post by:
Can somebody explain how the byte alignment for structures work, taking the following example and considering: byte of 1 Byte word of 2 Bytes dword of 4 Bytes typedef struct { byte a; word b;
15
6710
by: fix | last post by:
Hi all, I am writing a program using some structs, it is not running and I believe it is because there's some memory leak - the debugger tells me that the code causes the problem is in the malloc function. Is there any general rules that tell me when to allocate memory? I thought I don't have to if it is a variable that's not a pointer, and I have to if it is. I am a bit confused about the arrays particularly. In normal situations,...
13
2982
by: aegis | last post by:
The following was mentioned by Eric Sosman from http://groups.google.com/group/comp.lang.c/msg/b696b28f59b9dac4?dmode=source "The alignment requirement for any type T must be a divisor of sizeof(T). (Proof: In `T array;' both `array' and `array' must be correctly aligned.) Since `sizeof(unsigned char)' is divisible only by one and since one is a divisor of every type's size, every type is suitably aligned for `unsigned char'."
5
575
by: pt | last post by:
Hi, i am wonderng what is faster according to accessing speed to read these data structure from the disk in c/c++ including alignment handling if we access it on little endian system 32 bits system + OS e.g. Windows, Linux, WinCE. I am not quite sure about the alignment of the memory.... soln. 1: should be faster, I am not sure. idx size (bytes) 1 4
3
2493
by: Bill Pursell | last post by:
I have a program that does most of its work traversing a bunch of lists. The lists contain a void *, and I spent some time today replacing the void *'s with a copy of the data at the end of the structure as a zero length array. The performance improvement that resulted by avoiding the need to dereference the ptr was substantial, but it has left me with an uncertain feeling. In particular, changing an assignment caused the output to...
10
2195
by: haomiao | last post by:
I want to implement a common list that can cantain any type of data, so I declare the list as (briefly) --------------------------------------- struct list { int data_size; int node_num; char nodes; //will be list_node1,list_node2... };
66
3656
by: Why Tea | last post by:
typedef struct some_struct { int i; short k, int m; char s; } some_struct_t; Assuming 16 bit or 32-bit alignment, can I assume that s always gets 4 or 8 bytes of allocation due to padding
0
8503
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8488
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
8160
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
8358
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...
0
6826
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
5482
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
3972
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...
0
4036
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
1339
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.