January 12, 2004

我怎么了

我怎么了
突然觉得失去了方向
什么也不想做
什么也不想想

是杞人忧天
还是庸人自扰?
目标总是在地平线
而我却到不了

“舞秋风
漫天回忆舞秋风
叹一声
黯然沉默...”

耳边回荡着《秋意浓》
我的心
莫可名状

回避
抑或屈服
我嘲笑我的脆弱

是我想的太多
还是我付出的不够
还是选择新的开始

有一个故事
小女孩打开了一扇窗
看见了悲伤
不禁潸然泪下
爷爷为她打开另一扇窗
看见了欢乐
她也变得快乐

也许
是我的错
我打错了窗
面前的地平线不是我想去的远方

也许
是我的错
我应该走到另一面窗
那边的窗外的地平线
才有我的期待

我嘲笑的自己的脆弱
嘲笑自己的庸人自扰
嘲笑自己的天真

我怎么了
我不知道

只有此时回荡的音乐
才能描述

此刻的心情

Posted by victor at 06:07 PM | Comments (5)

January 11, 2004

一个有问题的程序段

详细文章

存在问题的程序
这个程序运行时会进入死循环,你知道为什么吗?
void loop();
void addr();

int main()
{
addr();
loop();
return 0;
}

long *p;

void loop()
{
long i, j;
j=0;
for(i=0; i<10; i++)
{
(*p)--;
j++;
}
}

void addr()
{
long k;
k=0;
p=&k;
}


分析
其实错误比较明显:上面这个程序中addr()里面p的指针指向了一个局部变量k,而在loop()中使用了这个指针。程序运行结果是进入死循环。为什么呢?

我们知道,局部变量是在栈中保存,在程序的入口处有如下的代码
push ebp
mov ebp,esp
push ecx
esp中保存的局部变量的栈空间的基地址。栈的结构如示意图所示:

在addr()中,
_k$ = -4
_addr PROC NEAR
push ebp ; bytes=1
mov ebp, esp ; bytes=2
push ecx ; bytes=1
; 26 : long k;
; 27 : k=0;
mov DWORD PTR _k$[ebp], 0 ; bytes=7
; 28 : p=&k;
lea eax, DWORD PTR _k$[ebp] ; bytes=3
mov DWORD PTR _p, eax ; bytes=5
mov esp, ebp ; bytes=2
pop ebp ; bytes=1
ret 0 ; bytes=1
_addr ENDP
变量p中的值为ebp+_k$(ebp寄存器的值加上_k$,即ebp-4)。执行过addr()后,程序转入loop()中运行:
_i$ = -4
_j$ = -8
_loop PROC NEAR
push ebp ; bytes=1
mov ebp, esp ; bytes=2
sub esp, 8 ; bytes=3
; 15 : long i, j;
; 16 : j=0;
mov DWORD PTR _j$[ebp], 0 ; bytes=7
; 17 : for(i=0; i<10; i++)
mov DWORD PTR _i$[ebp], 0 ; bytes=7
jmp SHORT $L471 ; bytes=2
$L472:
mov eax, DWORD PTR _i$[ebp] ; bytes=3
add eax, 1 ; bytes=3
mov DWORD PTR _i$[ebp], eax ; bytes=3
$L471:
cmp DWORD PTR _i$[ebp], 10 ; bytes=4, 0000000aH
jge SHORT $L473 ; bytes=2
; 19 : (*p)--;
mov ecx, DWORD PTR _p ; bytes=6
mov edx, DWORD PTR [ecx] ; bytes=2
sub edx, 1 ; bytes=3
mov eax, DWORD PTR _p ; bytes=5
mov DWORD PTR [eax], edx ; bytes=2
; 20 : j++;
mov ecx, DWORD PTR _j$[ebp] ; bytes=3
add ecx, 1 ; bytes=3
mov DWORD PTR _j$[ebp], ecx ; bytes=3
jmp SHORT $L472 ; bytes=2
$L473:
mov esp, ebp ; bytes=2
pop ebp ; bytes=1
ret 0 ; bytes=1
_loop ENDP

在这个函数中,变量i、j的地址为(ebp-4)、(ebp-8),各占4个字节。而此时i的地址恰好与p中的地址相等。因为两个函数的局部变量的栈是同一个栈。这样对(*p)操作等同于对i操作。
下面的代码可以更详细地表明:
mov eax, DWORD PTR _i$[ebp]
add eax, 1 ; i++
mov DWORD PTR _i$[ebp], eax
……
mov ecx, DWORD PTR _p
mov edx, DWORD PTR [ecx]
sub edx, 1 ; 等价于 i--
mov eax, DWORD PTR _p
mov DWORD PTR [eax], edx

这样,loop()中循环体中完成的操作的为i--,而循环控制语句为i++。i的值始终在0,-1间变化。程序显然进入了死循环。

归纳来说,全局变量p的本意希望指向addr()中的k,而在loop()中的p值却不再代表的addr()中的k,而是loop()中的i。这是由于局部变量的性质决定的。在loop()中 *p 的作用等效于i,导致出错也就在情理之中了。

结论
这个错误提醒我们,使用指针时千万不要调用失效的局部变量。调用失效的局部标量的指针很容易产生意想不到的结果。


Posted by victor at 05:29 PM | Comments (0)

January 01, 2004

2004新的一年

今天是2004年的第一天。我起得很晚。踏踏实实得睡了一觉,醒来后精力充沛,以一份好心情迎接2004。其实今天与昨天没有什么不同,但意义上迥异。今天是新的开始。“岁岁年年花相似,年年岁岁人不同”。

2003年会渐渐淡出视野,我面前的是2004年。站在新的起点,我不禁感叹时间的飞逝。过去的12个月,似乎就是昨天的12小时。我还在睡觉,我还在看书,我还在打球,我还在和哥们聊天、打星际......“当我洗脸时,时间从指间流逝”这一流逝便是一年。这一年里,我收获了什么?

最大的收获便是结识更多的朋友。无论是研究室里的朋友,还是在微软夏令营中的朋友,都是我人生中的贵人。朋友们优秀的一面不断地激励我前进。在新年来临之际,我愿意与他们分享这份喜悦,无论他们在上海、北京,还是在台北、香港。

新的一年,为新的梦想作序吧。

“ 寻梦?撑一支长篙,
 向青草更青处漫溯;
满载一船星辉,
 在星辉斑斓里放歌。

Posted by victor at 09:19 PM | Comments (1)