首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >可靠地触发别名错误的代码?

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

Stack Overflow用户
提问于 2014-05-17 12:56:14
回答 1查看 534关注 0票数 4

头衔几乎说明了一切。有人能给我指点或提供一些代码来可靠地触发gcc最近版本的别名错误吗?我问这个问题的原因是,我试图研究严格混叠的效果,但不管我多么努力地去违反它,gcc总会想出一个“正确”的结果,对你想要违反规则的情况进行任何测试。我并不是在问警告(-WSTINTE-别名=2对我所做的几乎所有事情都会发出警告),而是在使用-fStranced-别名进行优化时实际上会失败的代码。

代码语言:javascript
运行
复制
#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 );
    *f = 0.f;
    printf( " %u (%s)\n", var, 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 );
    *f = 0.f;
    printf( " %u (%s)\n", var, var != 100 ? "OK" : "FAIL" );
}

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

    // obvious rule violation:
    printf( "[test-1] int2 == %08X\n",
        ( (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 == %08X\n",
        *(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, int2 == %08X\n",
        ( ( __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, int2 == %08X\n",
        ( (  __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进行严格混叠:

代码语言:javascript
运行
复制
__attribute__( ( may_alias ) )

工作,但只有当添加到实际的结构定义(似乎并不重要,你选择哪一个)-在其他地方,它被默默地忽略了。

代码语言:javascript
运行
复制
__attribute__( ( optimize( "no-strict-aliasing" ) ) )

正如人们所怀疑的那样,这一点也没有影响。程序还挂着。

代码语言:javascript
运行
复制
#pragma GCC optimize "no-strict-aliasing"

同样,正如所怀疑的那样,这与上面的相同(没有)。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-05-17 14:54:04

这个程序虽然不是很有用,但很好地证明了GCC的混叠。在优化的代码版本中,GCC看到bp->a从未更改,并优化了整个程序,使其成为一个繁忙的循环:

代码语言:javascript
运行
复制
#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)

代码语言:javascript
运行
复制
  4003c0:   eb fe                   jmp    4003c0 <main>
  4003c2:   90                      nop
  4003c3:   90                      nop

GCC:

代码语言:javascript
运行
复制
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) 
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23711613

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档