当前位置: 技术问答>linux和unix
一个在Unix下的一个C程序??????????????????
来源: 互联网 发布时间:2015-12-09
本文导语: 请先看看下面的原程序: #include #include #include using namespace std; //static void f1(int , int ,int); static void f1(int *, int , int); static void f2(void); static jmp_buf jmpbuffer; int main(void) { int count; volatile int sum; register ...
请先看看下面的原程序:
#include
#include
#include
using namespace std;
//static void f1(int , int ,int);
static void f1(int *, int , int);
static void f2(void);
static jmp_buf jmpbuffer;
int main(void)
{
int count;
volatile int sum;
register int val;
count = 2; val = 3; sum = 4;
if(setjmp(jmpbuffer)!=0)
{
printf("after longjmp : count = %d,val = %d, sum = %d n", count,val,sum);
exit(0);
}
count = 96; val = 97; sum = 99;
f1(&count,val,sum);
//f1(count,val,sum);
}
/*
static void f1(int i, int j ,int k)
{
printf(" int f1(): count = %d,val = %d , sum = %dn",i, j , k);
f2();
}
*/
static void f1(int * i, int j ,int k)
{
printf(" int f1(): count = %d,val = %d , sum = %dn",*i, j , k);
f2();
}
static void f2(void)
{
longjmp(jmpbuffer,1);
}
以下是我的问题:
1. 当我用xlC -o temjmp temjmp.C时,输出的结果为:
int f1(): count = 96,val = 97 , sum = 99
after longjmp : count = 96,val = 97, sum = 99
当我用xlC -O temjmp temjmp.C时(也就是把编译器优化打开),输出的结果为:
int f1(): count = 96,val = 97 , sum = 99
after longjmp : count = 96,val = 3, sum = 99
不知道为什么?
2. 当我把sum的volatile去掉后,sum也变了.但是,我要问的是为什么count不会变.而在去掉了指针属性后会变.
请哪位高手给予帮忙!!!!!!!!!!!!!!!!!!!!!!!!!
#include
#include
#include
using namespace std;
//static void f1(int , int ,int);
static void f1(int *, int , int);
static void f2(void);
static jmp_buf jmpbuffer;
int main(void)
{
int count;
volatile int sum;
register int val;
count = 2; val = 3; sum = 4;
if(setjmp(jmpbuffer)!=0)
{
printf("after longjmp : count = %d,val = %d, sum = %d n", count,val,sum);
exit(0);
}
count = 96; val = 97; sum = 99;
f1(&count,val,sum);
//f1(count,val,sum);
}
/*
static void f1(int i, int j ,int k)
{
printf(" int f1(): count = %d,val = %d , sum = %dn",i, j , k);
f2();
}
*/
static void f1(int * i, int j ,int k)
{
printf(" int f1(): count = %d,val = %d , sum = %dn",*i, j , k);
f2();
}
static void f2(void)
{
longjmp(jmpbuffer,1);
}
以下是我的问题:
1. 当我用xlC -o temjmp temjmp.C时,输出的结果为:
int f1(): count = 96,val = 97 , sum = 99
after longjmp : count = 96,val = 97, sum = 99
当我用xlC -O temjmp temjmp.C时(也就是把编译器优化打开),输出的结果为:
int f1(): count = 96,val = 97 , sum = 99
after longjmp : count = 96,val = 3, sum = 99
不知道为什么?
2. 当我把sum的volatile去掉后,sum也变了.但是,我要问的是为什么count不会变.而在去掉了指针属性后会变.
请哪位高手给予帮忙!!!!!!!!!!!!!!!!!!!!!!!!!
|
应该是优化惹的祸,我记得以前看过资料,优化时慎用register变量,优化会自动使用register,而volatile变量一般不会被优化。不妨研究一下《代码大全》关于优化的部分。
你也可以分析一下汇编代码,比如
printf("after longjmp : count = %d,val = %d, sum = %d n", count,val,sum);
一句的汇编在优化后和优化前分别是下面两段,可以看出还是有区别的,有时间可以仔细查看一下参数的区别。
我试过,你这段代码在linux下也可以重现,不妨到linux下研究,用objdump可以得到汇编代码:
g++ -O -o test test.cpp
objdump -D -S test > test.S
80486da: 8b 45 f0 mov 0xfffffff0(%ebp),%eax
80486dd: 50 push %eax
80486de: 6a 03 push $0x3
80486e0: ff 75 ec pushl 0xffffffec(%ebp)
80486e3: 68 e8 88 04 08 push $0x80488e8
80486e8: e8 bf fe ff ff call 80485ac
80486f7: 8b 45 f0 mov 0xfffffff0(%ebp),%eax
80486fa: 50 push %eax
80486fb: ff 75 ec pushl 0xffffffec(%ebp)
80486fe: ff 35 e0 9b 04 08 pushl 0x8049be0
8048704: 68 28 89 04 08 push $0x8048928
8048709: e8 9e fe ff ff call 80485ac
你也可以分析一下汇编代码,比如
printf("after longjmp : count = %d,val = %d, sum = %d n", count,val,sum);
一句的汇编在优化后和优化前分别是下面两段,可以看出还是有区别的,有时间可以仔细查看一下参数的区别。
我试过,你这段代码在linux下也可以重现,不妨到linux下研究,用objdump可以得到汇编代码:
g++ -O -o test test.cpp
objdump -D -S test > test.S
80486da: 8b 45 f0 mov 0xfffffff0(%ebp),%eax
80486dd: 50 push %eax
80486de: 6a 03 push $0x3
80486e0: ff 75 ec pushl 0xffffffec(%ebp)
80486e3: 68 e8 88 04 08 push $0x80488e8
80486e8: e8 bf fe ff ff call 80485ac
80486f7: 8b 45 f0 mov 0xfffffff0(%ebp),%eax
80486fa: 50 push %eax
80486fb: ff 75 ec pushl 0xffffffec(%ebp)
80486fe: ff 35 e0 9b 04 08 pushl 0x8049be0
8048704: 68 28 89 04 08 push $0x8048928
8048709: e8 9e fe ff ff call 80485ac
|
真的是优化的问题。看看没优化的code:
0x08048437 : movl $0x2,0xfffffff0(%ebp) # count = 2
0x0804843e : movl $0x3,0xffffffe8(%ebp) # val =3
0x08048445 : movl $0x4,0xffffffec(%ebp) # sum =4
0x0804844c : movl $0x80497e0,(%esp)
0x08048453 : call 0x8048350 # setjmp()
0x08048458 : test %eax,%eax
0x0804845a : je 0x8048489 # if() 判断
0x0804845c : mov 0xffffffec(%ebp),%eax
0x0804845f : mov %eax,0xc(%esp)
0x08048463 : mov 0xffffffe8(%ebp),%eax
0x08048466 : mov %eax,0x8(%esp)
0x0804846a : mov 0xfffffff0(%ebp),%eax
0x0804846d : mov %eax,0x4(%esp)
0x08048471 : movl $0x8048640,(%esp)
0x08048478 : call 0x8048330
优化后的code:
0x08048436 : movl $0x2,0xffffffec(%ebp) # count = 2
0x0804843d : movl $0x4,0xfffffff0(%ebp) # sum =4
0x08048444 : movl $0x80497e0,(%esp)
0x0804844b : call 0x8048350
0x08048450 : test %eax,%eax
0x08048452 : je 0x8048482
0x08048454 : mov 0xfffffff0(%ebp),%eax
0x08048457 : mov %eax,0xc(%esp)
0x0804845b : movl $0x3,0x8(%esp) # val的地址被优化掉了直接用常数替换。因为count传给f1用的是指针,所有没有优化掉。
0x08048463 : mov 0xffffffec(%ebp),%eax
0x08048466 : mov %eax,0x4(%esp)
0x0804846a : movl $0x8048640,(%esp)
0x08048471 : call 0x8048330
。。。。
0x08048490 : mov 0xfffffff0(%ebp),%eax
0x08048493 : mov %eax,0x8(%esp)
0x08048497 : movl $0x61,0x4(%esp) # 传给f1的val也用常量代替
0x0804849f : lea 0xffffffec(%ebp),%eax
0x080484a2 : mov %eax,(%esp)
0x080484a5 : call 0x80484b7
最终解释是val的地址空间被gcc给优化掉了,都用常数替代,所有jump来jump去就出问题了。
0x08048437 : movl $0x2,0xfffffff0(%ebp) # count = 2
0x0804843e : movl $0x3,0xffffffe8(%ebp) # val =3
0x08048445 : movl $0x4,0xffffffec(%ebp) # sum =4
0x0804844c : movl $0x80497e0,(%esp)
0x08048453 : call 0x8048350 # setjmp()
0x08048458 : test %eax,%eax
0x0804845a : je 0x8048489 # if() 判断
0x0804845c : mov 0xffffffec(%ebp),%eax
0x0804845f : mov %eax,0xc(%esp)
0x08048463 : mov 0xffffffe8(%ebp),%eax
0x08048466 : mov %eax,0x8(%esp)
0x0804846a : mov 0xfffffff0(%ebp),%eax
0x0804846d : mov %eax,0x4(%esp)
0x08048471 : movl $0x8048640,(%esp)
0x08048478 : call 0x8048330
优化后的code:
0x08048436 : movl $0x2,0xffffffec(%ebp) # count = 2
0x0804843d : movl $0x4,0xfffffff0(%ebp) # sum =4
0x08048444 : movl $0x80497e0,(%esp)
0x0804844b : call 0x8048350
0x08048450 : test %eax,%eax
0x08048452 : je 0x8048482
0x08048454 : mov 0xfffffff0(%ebp),%eax
0x08048457 : mov %eax,0xc(%esp)
0x0804845b : movl $0x3,0x8(%esp) # val的地址被优化掉了直接用常数替换。因为count传给f1用的是指针,所有没有优化掉。
0x08048463 : mov 0xffffffec(%ebp),%eax
0x08048466 : mov %eax,0x4(%esp)
0x0804846a : movl $0x8048640,(%esp)
0x08048471 : call 0x8048330
。。。。
0x08048490 : mov 0xfffffff0(%ebp),%eax
0x08048493 : mov %eax,0x8(%esp)
0x08048497 : movl $0x61,0x4(%esp) # 传给f1的val也用常量代替
0x0804849f : lea 0xffffffec(%ebp),%eax
0x080484a2 : mov %eax,(%esp)
0x080484a5 : call 0x80484b7
最终解释是val的地址空间被gcc给优化掉了,都用常数替代,所有jump来jump去就出问题了。