1.問題發現
有這樣一段代碼:
#include <stdio.h>
int main()
{
int a, b, num1, num2, temp;
printf("please input two numbers:\n");
scanf("%d,%d", &num1, &num2);
if(num1 > 0 && num2 > 0) (1)
{
a = num1;
b = num2;
temp = a%b;
}
while(b != 0) (2)
{
a = b;
b = temp;
temp = a%b;
}
printf("gong yue shu : %d\n", a);
printf("gong bei shu : %d\n", num1*num2/a);
return 0;
}
該代碼輸入任何數字的執行結果(如圖1)都是“浮點數異常(核心已轉儲)”,剛剛見到這個問題讓人感覺摸不着頭緒,程序根本沒有用到浮點數,怎么會報告浮點數異常;
圖1.程序運行結果
2.問題分析
下面我們通過Linux自帶調試工具Gdb來進行調試,觀察程序的運行狀況。在編譯的是個加上“-g”選項,方便利用Gdb調試。
圖2.編譯和調試指令
程序編譯沒有錯誤,下面使用Gdb工具調試;在不知道問題產生根源的情況下,先在(1)處設置斷點,全速運行;
圖3.斷點之前運行情況
從圖3可見,進入斷點前,程序運行正常;下面查看變量num1、num2的值。
圖4.變量賦值情況
由圖4可見,變量num1、num2的值正常讀入。下面將斷點設置在(2)處,全速運行。
圖5.進入斷點2前程序運行情況
由圖4可見,進入while循環之前,程序正常運行。查看變量a、b賦值情況發現此時變量a、b均按照程序預期賦值。
圖6.變量a、b賦值情況
下面開始單步運行。由圖7可見,第一次循環結束變量a的值為4,b的值
圖7.第一次循環執行情況
為2,temp的值為0;繼續單步運行。從圖8可以看出,在第二次進入循環執行
圖8.第二次循環執行情況
語句“temp = a%b;”的時候出現了錯誤。分析變量值發現此時變量a的值為2,b的值為0,對0求余是沒有意義的,語法不允許。到此,問題水落石出。
現在,我們編寫測試代碼對問題產生原因進行驗證,代碼如下:
#include <stdio.h>
int main(int argc , char *argv[])
{
int a=5,b=0;
printf("%d\n",a%b);
return 0;
}
圖9.測試代碼運行情況
由圖9可見,該錯誤系求余運算符右邊操作數為0值所致。如果把測試代碼的“a%b”改為“a/b”,運行結果仍然是浮點數例外。求余運算和除法運算不允許右邊的操作數為0值,我們在編寫程序的時候需小心謹慎,注意程序的邏輯,避免之中錯誤的發生。問題代碼系網上引用,其中輾轉相除法的邏輯錯誤,此處不加討論。