Dereferencing type-punned pointer will break strict-aliasing rules

后端 未结 7 1458
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-01 01:05

I used the following piece of code to read data from files as part of a larger program.

double data_read(FILE *stream,int code) {
        char data[8];
              


        
相关标签:
7条回答
  • 2020-12-01 01:33

    The problem occurs because you access a char-array through a double*:

    char data[8];
    ...
    return *(double*)data;
    

    But gcc assumes that your program will never access variables though pointers of different type. This assumption is called strict-aliasing and allows the compiler to make some optimizations:

    If the compiler knows that your *(double*) can in no way overlap with data[], it's allowed to all sorts of things like reordering your code into:

    return *(double*)data;
    for(int i=7;i>=0;i--)
        data[i] = fgetc(stream);
    

    The loop is most likely optimized away and you end up with just:

    return *(double*)data;
    

    Which leaves your data[] uninitialized. In this particular case the compiler might be able to see that your pointers overlap, but if you had declared it char* data, it could have given bugs.

    But, the strict-aliasing rule says that a char* and void* can point at any type. So you can rewrite it into:

    double data;
    ...
    *(((char*)&data) + i) = fgetc(stream);
    ...
    return data;
    

    Strict aliasing warnings are really important to understand or fix. They cause the kinds of bugs that are impossible to reproduce in-house because they occur only on one particular compiler on one particular operating system on one particular machine and only on full-moon and once a year, etc.

    0 讨论(0)
提交回复
热议问题