On Tue, 19 Nov 2013 17:21:00 -0600, Raymond Lu said:
>The HDF5 library has its own alignment detection algorithm. I attached
>an excerpt of this algorithm as a standalone C program. There is a
>problem in this algorithm: in Line 30, the casting of a pointer to an
>integer may cause undefined behavior for some compilers.
In fact, you invoke undefined behaviour even earlier, at line 25. Nicely
explained with this example:
<https://www.securecoding.cert.org/confluence/display/seccode/EXP36-C.+Do+not+convert+pointers+into+more+strictly+aligned+pointer+types>
---------
void func(void) {
char c = 'x';
int *ip = (int *)&c; /* This can lose information */
char *cp = (char *)ip;
/* Will fail on some conforming implementations */
assert(cp == &c);
}
---------
Notice that that assert can fail! Evil, isn't it? But that's C, like it or
not! :)
Note that the compiler dutifully warns us:
align.c:25:13: warning: cast from 'unsigned char *' to 'int *' increases
required alignment from 1 to 4 [-Wcast-align]
p_int = (int *)p;
^~~~~~~~
>We're NOT interested in the alignment of a datatype in a structure. It
>refers to the value expressed in COMP_ALIGN in the following pseudo code:
>
> struct {
> char c;
> TYPE x;
> } s;
>
> COMP_ALIGN = (char*)(&(s.x)) - (char*)(&s);
I understand that you are *not* interested in struct offset/alignment, but *if*
you were, it would be best to use offsetof() instead of the above pseudo code:
<http://en.wikipedia.org/wiki/Offsetof>
>On Linux, for "int" type, the value of COMP_ALIGN is 4. The C keyword
>__alignof__ returns the alignment of the type in a structure, not the
>alignment of the type in memory.
I believe your description of __alignof__ is incorrect, see:
<http://gcc.gnu.org/onlinedocs/gcc/Alignment.html>
__alignof__ has nothing to do with structs. They even give an example showing
how it ignores padding added to structs. In other words, __alignof__ is NOT
the same as offsetof().
>Our library's algorithm of memory
>alignment finds that the alignment for "int" is 1, meaning no alignment
>restriction, on Linux.
What does __alignof__(int) give on that same system? 4 I bet.
Your attached align.c also gives "1" when run on my x86_64 Mac. It's only
giving us that result because we are lucky.
I have eliminated the undefined behaviour from your example (align2.c attached)
by eliminating the invalid cast and using memcpy() instead. You'll notice that
it will now output "alignment=1" all the time, since memcpy() is guaranteed
able to copy to/from memory of any alignment.
The conclusion, I'm afraid to say, is that your test is fundamentally flawed.
:( It's not answering the question "what is the minimun alignment of int?"
__alignof__(int) will give you that answer! It's answering the question: "if I
ignore the real minimun alignment, and try less and less, when will I crash?"
The fact that your current alignment detection is returning 1 for 'int' on
linux is a bug, it should return (probably) 4 (or whatever __alignof__ gives).
Back to your use case then:
---------
a memory buffer contains 2 elements of unsigned char. The values are 1 and 2:
unsigned char buf[8] = {1, 2, 0, 0, 0, 0, 0, 0};
H5Tconvert(H5T_NATIVE_UCHAR, H5T_NATIVE_INT, 2, buf, NULL, H5P_DEFAULT);
After the converting to int type, the values of the two data elements become
{0, 0, 0, 1, 0, 0, 0, 2} on a big-endian machine.
---------
With today's HDF5 code, on a system where your current alignment test gives 4
instead of 1, what would this do?
Cheers,
--
____________________________________________________________
Sean McBride, B. Eng [email protected]
Rogue Research www.rogue-research.com
Mac Software Developer Montréal, Québec, Canada
#include <stdio.h>
#include <setjmp.h>
#include <string.h>
#include <signal.h>
jmp_buf env;
int main(void)
{
int align_value[] = {1, 2, 4, 8, 16};
unsigned char buf[16];
int value2, type_value = 1;
int align_num = 0;
unsigned char *p;
/* Somehow similar to a while loop. Use it with longjmp. */
if(setjmp(env)) align_num++;
printf("--1--\n");
/* Shift the pointer in each loop to probe alignment */
p = (buf+align_value[align_num]);
printf("--2--\n");
memcpy(p, &type_value, sizeof(int));
printf("--3--\n");
/* This step may cause undefined behavior */
memcpy(&value2, p, sizeof(int));
printf("--4--\n");
/* If can't restore the original value, loop back and try another alignment
*/
if(type_value != value2)
longjmp(env, 1);
printf("alignment=%d\n", align_value[align_num]);
return 0;
}
_______________________________________________
Hdf-forum is for HDF software users discussion.
[email protected]
http://mail.lists.hdfgroup.org/mailman/listinfo/hdf-forum_lists.hdfgroup.org