加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

代码可靠地触发别名错误?

发布时间:2020-12-16 07:08:48 所属栏目:百科 来源:网络整理
导读:标题几乎说明了一切.有人可以指示我或者提供一些代码,这些代码可以使用最新版本的 gcc可靠地触发别名错误吗?我问的原因是我正在尝试研究严格混叠的影响,但无论我多么努力地违反它,gcc总会想出“正确”的结果,对如何处理你想要的情况进行任何测试打破规则几
标题几乎说明了一切.有人可以指示我或者提供一些代码,这些代码可以使用最新版本的 gcc可靠地触发别名错误吗?我问的原因是我正在尝试研究严格混叠的影响,但无论我多么努力地违反它,gcc总会想出“正确”的结果,对如何处理你想要的情况进行任何测试打破规则几乎没用.我不是在询问警告(-Wstrict-aliasing = 2会对我所做的一切提出警告),而是在使用-fstrict-aliasing进行优化时实际失败的代码.

#include <stdio.h>
#include <stdint.h>

typedef struct mystruct_s {
    uint32_t int1;
    uint32_t int2;
} mystruct_t;

typedef mystruct_t __attribute__( ( may_alias ) ) mystruct_alias_bad1_t;
// warning: ignoring attributes applied to ‘struct mystruct_s’ after definition [-Wattributes]
// so basically gcc is telling me i have to define it again if want an aliasable
// version?

typedef struct mystruct_alias_s {
    uint32_t int1;
    uint32_t int2;
} __attribute__( ( may_alias ) ) mystruct_alias_t;

static __attribute__( ( optimize( "no-strict-aliasing" ) ) ) void myfunc1_alias1( void ) {
    uint32_t var,*i = &var;
    float *f = (float*)&var;
    // warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
    // so __attribute__( ( optimize( "no-strict-aliasing" ) ) ) is either
    // not doing anything or gcc still gives warning even if the
    // optimization does not actually happen 

    *i = 100;
    printf( "[test-5] %u",var );
    *f = 0.f;
    printf( " %u (%s)n",var,var != 100 ? "OK" : "FAIL" );
}

#pragma GCC optimize "no-strict-aliasing"
static void myfunc1_alias2( void ) {
    uint32_t var,*i = &var;
    float *f = (float*)&var;
    // warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
    // this seems to be identical to the 
    // __attribute__( ( optimize( "no-strict-aliasing" ) ) ) case

    *i = 100;
    printf( "[test-6] %u",var != 100 ? "OK" : "FAIL" );
}
#pragma GCC optimize "strict-aliasing"

static void myfunc1( void ) {
    uint32_t var,*i = &var;
    float *f = (float*)&var;
    // warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
    // conclusion: pretty much none. all 3 functions generate exatcly the same
    // code that does just work as expected with no breakage at all despite the
    // warning so no-strict-aliasing on a per function level might do nothing
    // at all or just not for this code - no way to really tell...

    *i = 100;
    printf( "[test-7] %u",var != 100 ? "OK" : "FAIL" );
}

int main( int argc,char **argv ) {
    unsigned char buf[sizeof( mystruct_t )] = { 0x01,0x01,0x02,0x02 };

    // obvious rule violation:
    printf( "[test-1] int2 == %08Xn",( (mystruct_t*)buf )->int2
        // warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
    );
    // prints: [test-1] int2 == 2020202

    // pretty much the same as above but avoiding the struct:
    printf( "[test-2] int1 == %08X,int2 == %08Xn",*(uint32_t*)buf,// warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
        ( (uint32_t*)buf )[1]
        // warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
        // (you need -Wstrict-aliasing=2 - just -Wstrict-aliasing is not enough)
    );
    // prints: [test-2] int1 == 1010101,int2 == 2020202

    // lets try telling gcc that it should respect what we are trying to do:
    printf( "[test-3] int1 == %08X,( ( __attribute__( ( may_alias ) ) mystruct_t*)buf )->int1,// warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
        ( (mystruct_alias_t*)buf )->int2
        // this is the only one that works so far but it seems there is no way
        // to cast to such a pointer on the fly - you have to apply this
        // attribute to the original struct...
    );
    // prints: [test-3] int1 == 1010101,int2 == 2020202

    // lets try to be creative (basically make a mess with C99 anonymous arrays):
    printf( "[test-4] int1 == %08X,( (  __attribute__( ( may_alias ) ) mystruct_t* [1] ) { (mystruct_t*)buf } )[0]->int1,// warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
        // (you need -Wstrict-aliasing=2 - just -Wstrict-aliasing is not enough)
        // seems the attribute is ignored just as silently as for the direct cast
        ( ( mystruct_t* [1] ) { (mystruct_t*)buf } )[0]->int2
        // warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
        // (you need -Wstrict-aliasing=2 - just -Wstrict-aliasing is not enough)
        // i guess that evades -Wstrict-aliasing since that seems to pretty
        // much seems to only warn about code that casts and dereferences in one
        // go
    );
    // prints: [test-4] int1 == 1010101,int2 == 2020202

    // lets try to use __attribute__ optimize to disable strict aliasing temporaly:
    myfunc1_alias1();

    // lets try pragma:
    // #pragma GCC optimize "-fno-strict-aliasing"
    // error: #pragma GCC optimize is not allowed inside functions
    // (at least if you uncomment that line) so lets try a function again:
    myfunc1_alias2();

    // lets check if compiling the function without any makeup makes a difference:
    myfunc1();

    return 0;
}

最终编辑:

我现在没有时间更新代码,但我尝试了使用以下结果提供的代码mnunberg避免严格别名的不同方法:

__attribute__( ( may_alias ) )

只有在添加到实际结构定义时才会起作用(似乎无关紧要) – 其他地方默默无视.

__attribute__( ( optimize( "no-strict-aliasing" ) ) )

怀疑这根本没有效果.该计划仍然悬而未决.

#pragma GCC optimize "no-strict-aliasing"

同样怀疑这与上面的一样(没有).

解决方法

这个程序虽然不是很有用,但非常好地演示了GCC的别名.在优化版本的代码中,GCC认为bp-> a永远不会改变,并优化整个程序只是一个繁忙的循环:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    char *a;
    char *b;
} s_v;
typedef struct {
    char *a;
    char *b;
} s_b;

static inline void do_foo(s_v *buf,s_b *bp)
{
    buf->a = (char*)0x010;
    buf->b = (char*)0x020;
    bp->a = buf->a;
    bp->b = buf->b;
    while (bp->a) {
        buf->a--;
    }
}

int main(void)
{
    s_v *buf = malloc(sizeof (s_v));
    s_b *bp = (s_b*)buf;
    do_foo(buf,bp);
    return 0;
}

装配输出(objdump)

4003c0:   eb fe                   jmp    4003c0 <main>
  4003c2:   90                      nop
  4003c3:   90                      nop

GCC:

Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.7/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 4.7.3-4' --with-bugurl=file:///usr/share/doc/gcc-4.7/README.Bugs --enable-languages=c,c++,go,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.7 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.7 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --with-system-zlib --enable-objc-gc --with-cloog --enable-cloog-backend=ppl --disable-cloog-version-check --disable-ppl-version-check --enable-multiarch --with-arch-32=i586 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.7.3 (Debian 4.7.3-4)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读