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 s...@rogue-research.com 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. Hdf-forum@lists.hdfgroup.org http://mail.lists.hdfgroup.org/mailman/listinfo/hdf-forum_lists.hdfgroup.org