代码可靠地触发别名错误?
发布时间: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) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |