ຂໍ້ຜິດພາດທົ່ວໄປໃນການຂຽນໂປຣແກຣມ C++ ແລະວິທີແກ້ໄຂ
ການຂຽນໂປຣແກຣມ C++ ແມ່ນໜຶ່ງໃນພາສາການຂຽນໂປຣແກຣມທີ່ມີປະສິດທິພາບ ແລະ ມີຄວາມຍືດຫຍຸ່ນທີ່ສຸດ. ດ້ວຍຄວາມສາມາດໃນການຮອງຮັບການຂຽນໂປຣແກຣມແບບ procedure, object-oriented, ແລະ generic, C++ ຖືກນຳໃຊ້ຢ່າງກວ້າງຂວາງໃນແອັບພລິເຄຊັນທີ່ຫຼາກຫຼາຍ, ຕັ້ງແຕ່ລະບົບປະຕິບັດການຈົນເຖິງແອັບພລິເຄຊັນເກມທີ່ມີປະສິດທິພາບສູງ. ຢ່າງໃດກໍຕາມ, ເຊັ່ນດຽວກັບພາສາການຂຽນໂປຣແກຣມອື່ນໆ, C++ ຍັງມີຂໍ້ຜິດພາດທົ່ວໄປຈຳນວນໜຶ່ງທີ່ນັກພັດທະນາ, ທັງຜູ້ໃໝ່ ແລະ ຜູ້ມີປະສົບການ, ມັກພົບ. ບົດຄວາມນີ້ຈະປຶກສາຫາລືກ່ຽວກັບຂໍ້ຜິດພາດທົ່ວໄປບາງຢ່າງໃນການຂຽນໂປຣແກຣມ C++ ແລະ ໃຫ້ຄຳແນະນຳກ່ຽວກັບວິທີການແກ້ໄຂບັນຫາເຫຼົ່ານັ້ນ.
1. ການໃຊ້ຕົວຊີ້ທີ່ບໍ່ໄດ້ຕັ້ງຄ່າເລີ່ມຕົ້ນ
ຄວາມຜິດພາດ:
ຕົວຊີ້ທີ່ບໍ່ໄດ້ຕັ້ງຄ່າເລີ່ມຕົ້ນສາມາດຊີ້ໄປຫາຕຳແໜ່ງໜ່ວຍຄວາມຈຳທີ່ບໍ່ຮູ້ຈັກ, ເຊິ່ງເຮັດໃຫ້ເກີດພຶດຕິກຳທີ່ບໍ່ຄາດຄິດ ຫຼື ໂປຣແກຣມຂັດຂ້ອງ. ຕົວຢ່າງຂອງຄວາມຜິດພາດນີ້ແມ່ນດັ່ງຕໍ່ໄປນີ້:
“`cpp
int ptr; // ptr ບໍ່ໄດ້ຖືກເລີ່ມຕົ້ນ
ptr = 10; // ຄວາມຜິດພາດ: ຕົວຊີ້ບໍ່ໄດ້ຖືກເລີ່ມຕົ້ນ
“ `
ວິທີແກ້ໄຂ:
ເລີ່ມຕົ້ນຕົວຊີ້ກ່ອນການນຳໃຊ້. ທ່ານສາມາດເລີ່ມຕົ້ນມັນດ້ວຍ `nullptr` ຫຼື ດ້ວຍທີ່ຢູ່ໜ່ວຍຄວາມຈຳທີ່ຖືກຕ້ອງ.
“`cpp
int ptr = nullptr; // ເລີ່ມຕົ້ນດ້ວຍ nullptr
int ມູນຄ່າ = 10;
ptr = &ຄ່າ;
ptr = 20; // ດຽວນີ້ປອດໄພແລ້ວ
“ `
2. ຄວາມຜິດພາດໃນການຈັດການໜ່ວຍຄວາມຈຳ (ການຮົ່ວໄຫຼຂອງໜ່ວຍຄວາມຈຳ)
ຄວາມຜິດພາດ:
ການຮົ່ວໄຫຼຂອງໜ່ວຍຄວາມຈຳເກີດຂຶ້ນເມື່ອໜ່ວຍຄວາມຈຳທີ່ຈັດສັນໄວ້ບໍ່ໄດ້ຖືກປ່ອຍອອກມາໃໝ່. ສິ່ງນີ້ສາມາດເຮັດໃຫ້ແອັບພລິເຄຊັນໃຊ້ໜ່ວຍຄວາມຈຳຫຼາຍຂຶ້ນເລື້ອຍໆ, ເຊິ່ງໃນທີ່ສຸດຈະນຳໄປສູ່ການຂາດແຄນໜ່ວຍຄວາມຈຳ.
“`cpp
int ptr = int ໃໝ່[10];
// ລືມລຶບໜ່ວຍຄວາມຈຳທີ່ຈັດສັນໄວ້
“ `
ວິທີແກ້ໄຂ:
ໃຫ້ແນ່ໃຈວ່າໄດ້ເພີ່ມພື້ນທີ່ຄວາມຈຳທີ່ຈັດສັນໄວ້ໂດຍໃຊ້ `delete` ຫຼື `delete[]` ຂຶ້ນກັບສິ່ງທີ່ໃຊ້ເພື່ອຈັດສັນມັນ.
“`cpp
int ptr = int ໃໝ່[10];
// ການໃຊ້ໜ່ວຍຄວາມຈຳ…
delete[] ptr; // ໜ່ວຍຄວາມຈຳທີ່ຈັດສັນໄວ້ວ່າງ
“ `
ໃຊ້ຫ້ອງສະໝຸດຕົວຊີ້ອັດສະລິຍະ (ເຊັ່ນ `std::unique_ptr` ຫຼື `std::shared_ptr`) ເພື່ອເຮັດໃຫ້ການຈັດການໜ່ວຍຄວາມຈຳງ່າຍຂຶ້ນ.
“`cpp
ປະກອບດ້ວຍ
std::unique_ptr ptr(int ໃໝ່[10]);
// ໜ່ວຍຄວາມຈຳຈະຖືກປ່ອຍອອກໂດຍອັດຕະໂນມັດເມື່ອ ptr ອອກຈາກ scope
“ `
3. ຄວາມຜິດພາດໃນການໃຊ້ເອກະສານອ້າງອີງ
ຄວາມຜິດພາດ:
ການສົ່ງຄືນການອ້າງອີງ ຫຼື ຕົວຊີ້ໄປຫາຕົວແປທ້ອງຖິ່ນທີ່ຢູ່ນອກຂອບເຂດສາມາດເຮັດໃຫ້ເກີດພຶດຕິກຳທີ່ບໍ່ຄາດຄິດໄດ້.
“`cpp
int& ໄດ້ຮັບເອກະສານອ້າງອີງ() {
int ມູນຄ່າ = 10;
ຄ່າທີ່ສົ່ງຄືນ; // ຂໍ້ຜິດພາດ: ສົ່ງຄືນການອ້າງອີງເຖິງຕົວແປທ້ອງຖິ່ນ
}
“ `
ວິທີແກ້ໄຂ:
ຫຼີກລ່ຽງການສົ່ງຄືນການອ້າງອີງເຖິງຕົວແປທ້ອງຖິ່ນ. ແທນທີ່ຈະ, ໃຫ້ໃຊ້ຕົວແປຄົງທີ່, ຫຼືດີກວ່ານັ້ນ, ສົ່ງຄືນຄ່າ, ຫຼືພິຈາລະນາໃຊ້ວັດຖຸ.
“`cpp
int ຮັບຄ່າ() {
int ມູນຄ່າ = 10;
ຄ່າທີ່ສົ່ງຄືນ; // ປອດໄພກວ່າ
}
“ `
4. ບໍ່ສົນໃຈຂໍ້ຄວາມຜິດພາດ ແລະ ຄຳເຕືອນຂອງ Compiler
ຄວາມຜິດພາດ:
ໂປຣແກຣມເມີມັກຈະບໍ່ສົນໃຈຂໍ້ຄວາມຜິດພາດ ແລະ ຄຳເຕືອນທີ່ອອກໂດຍຄອມໄພເລີ, ເຖິງແມ່ນວ່າຂໍ້ຄວາມເຫຼົ່ານີ້ຈະໃຫ້ຂໍ້ມູນທີ່ສຳຄັນກ່ຽວກັບຄວາມຜິດພາດທີ່ອາດເກີດຂຶ້ນ.
ວິທີແກ້ໄຂ:
ກວດສອບ ແລະ ເຂົ້າໃຈຂໍ້ຄວາມຜິດພາດ ແລະ ຄຳເຕືອນທີ່ສ້າງຂຶ້ນໂດຍຄອມໄພເລີຢູ່ສະເໝີ. ໃຫ້ເປີດໃຊ້ຄຳເຕືອນລະດັບສູງເພື່ອຮັບປະກັນວ່າລະຫັດຈະສະອາດກວ່າ.
ຕົວຢ່າງໃນ GCC, ໃຊ້ທຸງ `-Wall` ເພື່ອສ້າງຄຳເຕືອນເພີ່ມເຕີມ.
“`ບ້າ
g++ -Wall -o ໂປຣແກຣມ main.cpp
“ `
5. ຄວາມຜິດພາດໃນການໂຫຼດເກີນຂອງຜູ້ປະກອບການ
ຄວາມຜິດພາດ:
ການໂຫຼດເກີນຂອງຕົວປະຕິບັດການທີ່ບໍ່ຖືກຕ້ອງສາມາດເຮັດໃຫ້ເກີດພຶດຕິກຳທີ່ບໍ່ຄາດຄິດ ຫຼື ຄວາມຜິດພາດໃນເວລາແລ່ນໄດ້.
“`cpp
ຫ້ອງຮຽນ MyClass {
ສາທາລະນະ:
ຂໍ້ມູນ int;
ຕົວປະຕິບັດການ MyClass+ (const MyClass& ອື່ນໆ) {
ສົ່ງຄືນຂໍ້ມູນ + other.data; // ຄວາມຜິດພາດ: ຄວນສົ່ງຄືນ MyClass
}
};
“ `
ວິທີແກ້ໄຂ:
ໃຫ້ແນ່ໃຈວ່າຕົວປະຕິບັດການທີ່ໂຫຼດເກີນສົ່ງຄືນປະເພດທີ່ເໝາະສົມ ແລະ ຮັກສາຄ່າຄົງທີ່ຂອງຄລາສໄວ້.
“`cpp
ຫ້ອງຮຽນ MyClass {
ສາທາລະນະ:
ຂໍ້ມູນ int;
ຕົວປະຕິບັດການ MyClass+ (const MyClass& ອື່ນໆ) {
ຜົນໄດ້ຮັບ MyClass;
ຂໍ້ມູນຜົນໄດ້ຮັບ = ຂໍ້ມູນ + ຂໍ້ມູນອື່ນໆ;
ສົ່ງຄືນຜົນໄດ້ຮັບ; // ສົ່ງຄືນວັດຖຸຈາກ MyClass
}
};
“ `
6. ການໃຊ້ມາໂຄຣໃນທາງທີ່ຜິດ
ຄວາມຜິດພາດ:
ບາງຄັ້ງມາໂຄຣຖືກໃຊ້ຫຼາຍເກີນໄປ ຫຼື ບໍ່ຖືກຕ້ອງ, ເຊິ່ງສາມາດນໍາໄປສູ່ຄວາມຜິດພາດທີ່ຍາກທີ່ຈະກວດພົບໃນເວລາແລ່ນ.
“`cpp
ກຳນົດ SQUARE(x) xx
int ຜົນໄດ້ຮັບ = SQUARE(5 + 1); // ຄວາມຜິດພາດ: ຜົນໄດ້ຮັບແມ່ນ 5 + 1 5 + 1
“ `
ວິທີແກ້ໄຂ:
ປ່ຽນມາໂຄຣດ້ວຍນິພົດຄົງທີ່ ຫຼື ແມ່ແບບເພື່ອຄວາມປອດໄພ ແລະ ການຄວບຄຸມຕົວອັກສອນທີ່ດີກວ່າ.
“`cpp
ແມ່ແບບ
ຮູບສີ່ຫຼ່ຽມ T (T x) {
ສົ່ງຄືນ xx;
}
int ຜົນໄດ້ຮັບ = square(5 + 1); // ປອດໄພໃນການໃຊ້
“ `
7. ການໃຊ້ຟັງຊັນແບບ C ໃນທາງທີ່ຜິດ
ຄວາມຜິດພາດ:
ການໃຊ້ຟັງຊັນແບບ C ເຊັ່ນ `strcpy` ຫຼື `sprintf` ເຊິ່ງມີຄວາມສ່ຽງຕໍ່ການຮົ່ວໄຫຼຂອງ buffer overflow.
“`cpp
char src[] = "ສະບາຍດີຊາວໂລກ!";
ຈຸດໝາຍປາຍທາງ char[5];
strcpy(dest, src); // ຂໍ້ຜິດພາດ: ບັຟເຟີລົ້ນ
“ `
ວິທີແກ້ໄຂ:
ໃຊ້ຟັງຊັນ C++ ທີ່ປອດໄພກວ່າເຊັ່ນ `std::string` ຫຼື `std::vector`.
“`cpp
ປະກອບດ້ວຍ
std::string src = “ສະບາຍດີ, ທົ່ວໂລກ!”;
std::string dest = src;
“ `
8. ການບໍ່ສົນໃຈການກວດສອບຄວາມຜິດພາດ
ຄວາມຜິດພາດ:
ບໍ່ສົນໃຈການກວດສອບຄວາມຜິດພາດໃນການດຳເນີນງານ I/O ຫຼື ຟັງຊັນຕ່າງໆທີ່ອາດຈະລົ້ມເຫຼວ.
“`cpp
ໄຟລ໌ std::ifstream(“data.txt”);
// ຄວາມຜິດພາດ: ບໍ່ໄດ້ກວດສອບວ່າໄຟລ໌ຖືກເປີດສຳເລັດແລ້ວຫຼືບໍ່
“ `
ວິທີແກ້ໄຂ:
ໃຫ້ກວດສອບຢູ່ສະເໝີວ່າການດຳເນີນງານປະສົບຜົນສຳເລັດຫຼືບໍ່ ແລະ ຈັດການກັບຂໍ້ຜິດພາດຢ່າງເໝາະສົມ.
“`cpp
ໄຟລ໌ std::ifstream(“data.txt”);
ຖ້າ (!ໄຟລ໌) {
std::cerr << “ບໍ່ສາມາດເປີດໄຟລ໌ໄດ້” << std::endl;
return 1
}
“ `
9. ການປະຕິບັດວົງຈອນທີ່ບໍ່ດີທີ່ສຸດ
ຄວາມຜິດພາດ:
ການໃຊ້ loops ທີ່ບໍ່ດີສຸດສາມາດເຮັດໃຫ້ປະສິດທິພາບຂອງໂປຣແກຣມຫຼຸດລົງ.
“`cpp
ສຳລັບ (int i = 0; i < vec.size(); i++) {
// ປະມວນຜົນດ້ວຍ vec[i]
// ຂໍ້ຜິດພາດ: size() ຖືກເອີ້ນໃຊ້ໃນທຸກໆ iteration
}
“ `
ວິທີແກ້ໄຂ:
ເພີ່ມປະສິດທິພາບຂອງ loops ໂດຍການຫຼຸດຜ່ອນການເອີ້ນຟັງຊັນຊ້ຳໆ.
“`cpp
ສຳລັບ (std::size_t i = 0, n = vec.size(); i < n; i++) {
// ປະມວນຜົນດ້ວຍ vec[i]
}
“ `
ໃຊ້ປະໂຫຍດຈາກອັລກໍຣິທຶມ STL ເຊັ່ນ `std::for_each` ສຳລັບການເພີ່ມປະສິດທິພາບຕື່ມອີກ.
“`cpp
ປະກອບດ້ວຍ
std::for_each(vec.begin(), vec.end(), [](int &value) {
// ຂະບວນການທີ່ມີຄ່າ
});
“ `
10. ຄວາມຜິດພາດໃນການຈັດການກະທູ້
ຄວາມຜິດພາດ:
ການຈັດການກະທູ້ທີ່ບໍ່ຖືກຕ້ອງສາມາດນໍາໄປສູ່ສະພາບການແຂ່ງຂັນຫຼືການຢຸດສະງັກ.
“`cpp
ປະກອບມີການແລ່ນ void() {
// ຄວາມຜິດພາດ: ອາດເກີດສະພາບເຊື້ອຊາດຂຶ້ນ
}
std::thread t1(ແລ່ນ);
std::thread t2(ແລ່ນ);
“ `
ວິທີແກ້ໄຂ:
ໃຊ້ຫຼັກການການຊິ້ງຂໍ້ມູນເບື້ອງຕົ້ນເຊັ່ນ: mutexes ເພື່ອປ້ອງກັນສະພາບການແຂ່ງຂັນ ແລະ ການຢຸດສະງັກ.
“`cpp
ລວມທັງລວມທັງ
std::mutex mtx;
ການເຮັດວຽກເປັນໂມຄະ() {
std::lock_guard ລັອກ(mtx);
// ຂະບວນການທີ່ປອດໄພຈາກສະພາບການແຂ່ງຂັນ
}
std::thread t1(ແລ່ນ);
std::thread t2(ແລ່ນ);
t1.ເຂົ້າຮ່ວມ();
t2.ເຂົ້າຮ່ວມ();
“ `
ສະຫຼຸບ
C++ ເປັນພາສາການຂຽນໂປຣແກຣມທີ່ມີປະສິດທິພາບ ແລະ ມີຄວາມຍືດຫຍຸ່ນ, ແຕ່ມັນຍັງມັກຈະມີຂໍ້ຜິດພາດທົ່ວໄປ, ໂດຍສະເພາະກ່ຽວກັບໜ່ວຍຄວາມຈຳ ແລະ ການຈັດການຕົວຊີ້. ໂດຍການເຂົ້າໃຈຂໍ້ຜິດພາດເຫຼົ່ານີ້ ແລະ ຮູ້ວິທີແກ້ໄຂ, ທ່ານສາມາດ ພັດທະນາ ແອັບພລິເຄຊັນທີ່ໜ້າເຊື່ອຖື ແລະ ມີປະສິດທິພາບຫຼາຍຂຶ້ນ. ຈົ່ງຈື່ໄວ້ວ່າໃຫ້ເອົາໃຈໃສ່ກັບຂໍ້ຄວາມຂອງຄອມໄພເລີຢູ່ສະເໝີ, ໃຊ້ເຄື່ອງມືທີ່ທັນສະໄໝທີ່ຊ່ວຍໃຫ້ທ່ານ ຂຽນລະຫັດທີ່ປອດໄພ , ແລະ ຝຶກຝົນທັກສະຂອງທ່ານຢ່າງຕໍ່ເນື່ອງໃນການເຂົ້າໃຈ ແລະ ນຳໃຊ້ວິທີປະຕິບັດທີ່ດີທີ່ສຸດໃນການຂຽນໂປຣແກຣມ C++.