[單班計程] 程式補完計畫 特別話: volatile
話說最後一次的課程在難得的準時下課下結束了,
但... 還沒結束呢... 這只是一切的開端...
各位應該還記得最後一話有一個 volatile 吧?
當時司令是將其草草帶過了,
但是事實上它會被安排在 signal 之前是有其特殊的意義的,
而且其功能就實務上常常難以取代, 所以現在來詳談 volatile.
先來談談 signal.
signal 其實是有一點非常特殊的性質的,
我們來看看這份 code:
--------------------------------------------------
int main(){
for(;1;){
}
return 0;
}
--------------------------------------------------
任何人應該都認為這是一個跑不完的程式吧?
程式的流程走進無窮的 for 迴圈,
眼前是大括號的重重包圍, 無路可逃.
但是事實上在這看似死牢的 for 中卻有一道空間的裂縫,
那就是 signal, 它可以讓你的程式流程瞬間傳送到 signal 的 handler,
signal 超脫了自然的定律, 是 compiler 完全無法預期的.
接下來我們再看這一份 code:
--------------------------------------------------
int a;
int main(){
for(a=1;a;){
}
return 0;
}
--------------------------------------------------
從這份 code 我們看到了什麼?
a 在進到 for 的時候被設成了 1,
然後迴圈中沒有任何一行有變動它,
所以 compiler 很有可能認為迴圈中的 a 可以不用看就知道是 1,
而將我們的 for 變成這樣: for(a=1;1;)
這樣看起來也很合理吧?
最後我們來看這一份 code:
--------------------------------------------------
int a;
void sighand(int signo){
printf ("Don't kill me. I'll suicide.\n");
a = 0;
}
int main(){
signal (2, sighand);
for (a=1;a;){
}
return 0;
}
--------------------------------------------------
對於這份 code, compiler 也很有可能認為會動到 a 的只有 sighand,
而進入 for 之後, 再也沒有出現過 sighand, 所以認為 a 在 for 中會是定值 1,
因此而將我們的 for(a=1;a;) 變成 for(a=1;1;).
但是 compiler 錯了.
由於 signal 這個空間的裂縫,
我們可以經由 kill -2 [pid] 將程式的流程跳入 sighand,
因此 a 是定值 1 這件假設在預期外的情形被打破了,
在這裡即使我們被 kill -2, for 仍然會鐵齒地認為 a 仍然是 1,
所以不用出去, 結果該跳出的迴圈沒有跳出.
為了避免這個問題, 我們的主角 volatile 登場了.
volatile 本意並不是司令所講的"禁止最佳化",
它的本意其實是用來告訴 compiler 該變數可能會產生預期外的變動,
所以不要對該變數的內容太鐵齒,
為了達成這目標的副作用就是造成許多最佳化無法進行.
所以, 上面的 code 改成以下就保證可以正確執行:
--------------------------------------------------
volatile int a;
void sighand(int signo){
printf ("Don't kill me. I'll suicide.\n");
a = 0;
}
int main(){
signal (2, sighand);
for (a=1;a;){
}
return 0;
}
--------------------------------------------------
這個時候我們的 compiler 雖然一心認為 a 在 for 裡面應該要會是定值 1,
但是由於 volatile 的叮嚀,
最後 compiler 還是要求我們的程式每跑一圈一定要確實檢查 a,
結果我們真的抓到 sighand 偷換了 a 的值, 而能夠正常的結束迴圈.
圓滿的大結局不是嗎? ;)
--
その乾いた哀愁の瞳に去來するものは何か?
失ったもの 得たもの
そして廣大なネットの狹間で彼が見たものとは?
虛像と實存と記號の中に彼は今、何を想うのか?
<バトルプログラマーシラセ>
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.112.30.49
推
推 140.112.25.181 01/07, , 1F
推 140.112.25.181 01/07, 1F
推
推140.112.171.150 01/07, , 2F
推140.112.171.150 01/07, 2F
推
推 61.230.50.184 01/07, , 3F
推 61.230.50.184 01/07, 3F
推
推 140.112.25.182 01/08, , 4F
推 140.112.25.182 01/08, 4F
推
推 140.112.28.27 01/08, , 5F
推 140.112.28.27 01/08, 5F