人人都寫過的6個bug
大家好,我是知微。
程序員寫bug幾乎是家常便飯,也是我們每個人成長過程中難以避免的一部分。
為了緩解這份“尷尬”,今天想和大家分享一些曾經(jīng)都會遇到過的bug,讓我們一起來看看這些“經(jīng)典之作”。
1、數(shù)組越界
#include <stdio.h>
int main() {
int array[5];
array[5] = 42;
printf("幸運數(shù)字是:%d\n", array[5]);
return 0;
}
- 在這段代碼中,我們聲明了一個包含5個整數(shù)的數(shù)組,但隨后我們嘗試給數(shù)組的第六個元素(
array[5])賦值。 - 在C語言中,數(shù)組的索引是從0開始的,所以實際上我們只有
array[0]到array[4]這五個有效的元素。 - 因此,嘗試給第六個元素賦值會導致數(shù)組越界。
這種越界行為可能會導致程序崩潰、產(chǎn)生未定義的行為,甚至可能影響到程序的其他部分。

2、忘記給變量賦初值
忘記給變量賦初值是一個常見的編程錯誤,有時候它會導致程序運行時出現(xiàn)意外的行為。讓我們來看一個例子:
#include <stdio.h>
int main() {
int a = 5;
int b;
printf("a的值是:%d\n", a);
printf("b的值是:%d\n", b);
return 0;
}
-
在這段代碼中,我們給變量
a賦了初值為5,但變量b卻沒有被初始化。 -
在C語言中,未初始化的局部變量會包含一些隨機的垃圾值,這樣在使用它們的時候就會出現(xiàn)問題。
-
修復這個問題的方式是給變量
b一個明確的初值,如:
int b = 0;
或者根據(jù)實際需求選擇一個適當?shù)某踔担@樣可以避免在程序中使用未初始化的變量而引發(fā)的問題。

3、條件判斷寫成賦值
如果把 = 寫成了 ==,本來是判斷相等的,結(jié)果變成了賦值。條件永遠成立,導致程序執(zhí)行了不該執(zhí)行的分支。
#include <stdio.h>
int main() {
int x = 10;
if (x = 5) {
printf("條件成立!\n");
} else {
printf("條件不成立!\n");
}
return 0;
}
- 在這個例子中,條件判斷中使用了單個等號(
=)而不是比較相等的雙等號(==)。 - 這將導致
x被賦值為5,然后條件判斷始終為真,執(zhí)行了不該執(zhí)行的分支。

4、內(nèi)存未釋放或者重復釋放
a、內(nèi)存未釋放
#include <stdlib.h>
int main() {
int *arr = malloc(10 * sizeof(int));
// 忘記釋放內(nèi)存
// free(arr);
return 0;
}
- 在這個例子中,我們使用
malloc分配了一塊內(nèi)存來存儲整數(shù)數(shù)組,但是忘記了在程序結(jié)束前釋放這塊內(nèi)存。 - 這樣會導致內(nèi)存泄漏,即分配的內(nèi)存無法被回收,最終可能耗盡系統(tǒng)的可用內(nèi)存。
b、重復釋放內(nèi)存
#include <stdlib.h>
int main() {
int *arr = malloc(10 * sizeof(int));
// 重放釋放內(nèi)存
free(arr);
free(arr);
return 0;
}
- 在這個例子中,我們錯誤地嘗試釋放相同的內(nèi)存塊兩次。
- 這種情況可能導致程序崩潰或者其他未定義的行為,因為系統(tǒng)會認為這塊內(nèi)存已經(jīng)被釋放,再次釋放它會產(chǎn)生問題。
看到這里有人會有疑問,誰會這么傻,在一個地方free兩次,我free一次不就好了。
的確,我們在寫代碼的時候,基本不會出現(xiàn)例子中這種情況。但是我接下來要說的場景,還是很有可能發(fā)生的。
假如在a文件中申請了動態(tài)內(nèi)存,指針arr指向這塊內(nèi)存。b文件中free(arr), 然后某次不小心,在c文件中又free(arr),這種情況就會導致重復釋放內(nèi)存了。
5、強制類型轉(zhuǎn)換
#include <stdio.h>
int main() {
int a = 5;
float b = 2.5;
// 無名的類型強制可能導致精度損失
int result = (int)b + a;
printf("結(jié)果是:%d\n", result);
return 0;
}
-
在這個例子中,我們試圖將浮點數(shù)
b強制轉(zhuǎn)換為整數(shù),并與整數(shù)a相加。這可能導致精度損失,因為浮點數(shù)可能包含小數(shù)部分,但在強制轉(zhuǎn)換時小數(shù)部分將被丟棄,導致結(jié)果不準確。 -
在進行類型轉(zhuǎn)換時,需要仔細考慮可能發(fā)生的精度損失,并確保結(jié)果仍然符合預期。如果可能會有精度損失,最好考慮使用更合適的數(shù)據(jù)類型或者進行四舍五入等操作以確保精度。
6、使用未初始化的指針
未初始化的指針可能包含隨機的內(nèi)存地址,導致未定義的行為。
#include <stdio.h>
int main() {
int *ptr;
// 使用未初始化的指針
*ptr = 42;
printf("值:%d\n", *ptr);
return 0;
}
-
在這個例子中,指針
ptr沒有被初始化,但卻嘗試通過它來訪問內(nèi)存并賦值。 -
這可能導致程序崩潰或者產(chǎn)生不可預測的結(jié)果,因為指針
ptr實際上指向了一個未知的內(nèi)存地址。 -
為了避免這個問題,始終確保在使用指針之前對其進行初始化。例如,通過分配內(nèi)存或?qū)⑵渲赶蛞粋€已有的變量:
int value = 42;
int *ptr = &value; // 初始化指針,指向變量 value
printf("值:%d\n", *ptr);
- 或者,如果不想立即初始化,可以將指針設(shè)置為
NULL(空指針),然后在需要時再進行初始化:
int *ptr = NULL; // 初始化為空指針
// 在需要時分配內(nèi)存或指向已有變量
// ...
printf("值:%p\n", (void *)ptr); // 注意:%p 用于打印指針的地址
- 通過這樣的方式,可以確保在使用指針之前,它已經(jīng)指向了有效的內(nèi)存地址,避免了潛在的未定義行為。
?以上就是本文的全部內(nèi)容了?!
??歡迎各位 ??點贊 ?收藏 ??評論,如有錯誤請留言指正,非常感謝!

浙公網(wǎng)安備 33010602011771號