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

Reply via email to