This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Is there a warning / Info to avoiding alignment traps

Hello all,

 

regarding TMS320F2833x it is possible to write such things:

// Declaration with global scope
int i[10];

struct s
{
long l;
};

// somewhere in a function:
struct s * p;

p = &i[0];

long A = p->l;

p = &i[1];

long B = p->l;

Because of the alignment A and B have the same values.

Is there a possibility to raise an error regarding this topic:
Like "because of alignment p may have corrupt data"...

Thanks for your help!

JD
  • Well, when you build that, you will get error diagnostics like this one ...

        "file.c", line 15: error: a value of type "int *" cannot be assigned to an
                  entity of type "struct s *"
            p = &i[1];
              ^
    

    You can avoid the diagnostic with a cast. But I don't recommend that approach at all. What is the overarching problem you want to solve? There is probably a better way to do it.

    Thanks and regards,

    -George

  • Hi!

     

    Indeed the code includes the casts:

        // somewhere in a function: struct s * p;


    p = (struct s *) &i[0];

    long A = p->l;

    p = (struct s *) &i[1];

    long B = p->l;

    The problem is, that in that example reading from an odd address results
    in something you did not expect because of the alignment.

    So I need the warning, whenever a pointer is used and points to something
    which may be an odd address in case of different pointer types are used.

    In the example it was int and long.

    Is the problem clearer now?

    JD

  • Accessing an object through a pointer to a different type invokes undefined behavior, which means the compiler will not promise to do what you expect.  Sometimes you can get away with such a cast, but at a minimum the alignment needs to be right, and it's still technically undefined behavior.

    See also the C-FAQ entry on undefined behavior.

    The one exception is that any object may be accessed through a pointer to unsigned char.  You can do a byte-by-byte copy out of the int array with memcpy.

  • Are you trying to define a single integer array and use it as if it were an array of various other types at different points in your program?  If so, you would be better off defining an array of structs instead of casting a pointer to an array of integers.

    If it's essential to overlay different arrays to share storage, use a union;  that's what they're for.  It's also easier to read.

    By using an array of the struct type you mean, whether solo or within a union, you allow the compiler to align the fields properly.

  • Hi everybody,

     

    it is interesting to see, that you all wonder what I want to do.

    Indeed, the question is not answered.

    Fact is, reading via a pointer from an odd address gives you undefined behaviour,

    when the alignment of int is 1 (variable) and the alignment of long is 2 (pointer access).

    As we all know this, is the compiler able to tell the developer, he has done something absolutely dangerous.

    What is the error number.

    Background is a large project, were many developers work on a codebase. The last two days I searched

    a bug  and finally found it. Data was stored in an int array,  then similar to the example above the struct pointer

    was used to fetch the data from the array. This is not common programming practice but it was finally coded in such a way.

    A simple warning generated by the compiler might have given a hint.

    So is there a warning available for such a topic?

     

    JD

  • Oh I see.  Well, there isn't such an option in any released TI compiler, and I can't find one in GCC, either.  The traditional philosophy is that since the user intentionally added an explicit cast, the user must know something the compiler doesn't.  In this case, that's not true, but the cast will still fool the compiler.

    There is a MISRA-C rule for this particular case, but MISRA-C checking is unsupported at this time.

  • I just found a related warning in GCC.  (This test case was compiled on a Solaris machine; on Linux you won't get the warning.)

    % gcc -Wcast-align danger.c
    danger.c: In function 'fn':
    danger.c:4: warning: cast increases required alignment of target type
    danger.c:7: warning: cast increases required alignment of target type
    
    % cat danger.c
    void fn(void)
    {
        short a;
        long long *b = (long long *)&a;
    
        short c[10];
        long long *d = (long long *)c;
    }
    

    [EDIT: original test case was flawed, fixed post accordingly - Archaeologist]

  • Ok, thanks a lot for all your support.
    Have a nice afternoon :)

    JD