UBSan และ TSan
ค้นหาพฤติกรรมไม่กำหนดและการแข่งขัน
UBSan และ TSan เป็นบทเรียน C++ Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C++ Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C++ Academy มีบทเรียนทั้งหมด 4 บทเรียน
ตัวตรวจสอบอีกสองชนิด
นอกจากเอเอสแซนแล้ว ยังมีตัวตรวจสอบอีกสองชนิดที่มุ่งตรวจจับข้อบกพร่องคนละประเภท
- ยูบีแซน: พฤติกรรมที่ไม่กำหนดไว้ (ค่าล้น การเลื่อนบิตผิด การอ้างอิงตัวชี้ว่าง)
- ทีแซน: การแย่งข้อมูลในโค้ดหลายเธรด
การเปิดใช้ยูบีแซน
เปิดใช้ UndefinedBehaviorSanitizer ด้วย -fsanitize=undefined และสามารถใช้ร่วมกับเอเอสแซนได้
g++ -fsanitize=undefined -g main.cpp -o app
./appจำนวนเต็มมีเครื่องหมายล้น
จำนวนเต็มมีเครื่องหมายล้นถือเป็นพฤติกรรมที่ไม่กำหนดไว้ใน C++ ยูบีแซนจะแจ้งเตือนที่บรรทัดที่เกิดเหตุโดยตรง
#include <climits>
#include <iostream>
int main() {
int x = INT_MAX;
int y = x + 1; // signed overflow: UB
std::cout << y << "\n";
return 0;
}พฤติกรรมที่ไม่กำหนดไว้อื่น ๆ ที่ยูบีแซนตรวจจับได้
ยูบีแซนตรวจจับข้อผิดพลาดแฝงได้หลายชนิด
- การเลื่อนบิตเกินช่วง (
x << 40สำหรับจำนวนเต็ม 32 บิต) - การอ้างอิงตัวชี้ว่าง
- การเข้าถึงที่จัดแนวไม่ถูกต้อง
- ค่าของ enum หรือบูลีนไม่ถูกต้อง
ทำให้ยูบีแซนหยุดทำงาน
โดยค่าเริ่มต้น ยูบีแซนจะแสดงข้อความแล้วทำงานต่อ เพิ่ม -fno-sanitize-recover=undefined เพื่อยุติการทำงานเมื่อพบข้อผิดพลาดแรก ซึ่งเหมาะกับการผสานรวมอย่างต่อเนื่องมากกว่า
g++ -fsanitize=undefined -fno-sanitize-recover=undefined -g main.cpp -o appการเปิดใช้ทีแซน
เปิดใช้ ThreadSanitizer ด้วย -fsanitize=thread โดยจะตรวจจับการแย่งข้อมูล ซึ่งเกิดเมื่อสองเธรดเข้าถึงหน่วยความจำเดียวกันโดยไม่มีการประสานงาน และมีอย่างน้อยหนึ่งเธรดเขียนข้อมูล
g++ -fsanitize=thread -g main.cpp -o app -pthread
./appตัวอย่างการแย่งข้อมูล
สองเธรดเพิ่มค่าตัวนับที่ใช้ร่วมกันโดยไม่มีการล็อก ทีแซนจะแจ้งการเข้าถึงที่แย่งกันและสแตกของการเข้าถึงเหล่านั้น
#include <thread>
#include <iostream>
int counter = 0;
void work() { for (int i = 0; i < 1000; ++i) ++counter; }
int main() {
std::thread t1(work), t2(work);
t1.join();
t2.join();
std::cout << counter << "\n";
return 0;
}การแก้การแย่งข้อมูล
ปกป้องข้อมูลที่ใช้ร่วมกันด้วยมิวเท็กซ์ หรือใช้ std::atomic หลังแก้ไขแล้ว ทีแซนจะไม่รายงานการแย่งข้อมูล
#include <thread>
#include <atomic>
#include <iostream>
std::atomic<int> counter{0};
void work() { for (int i = 0; i < 1000; ++i) ++counter; }
int main() {
std::thread t1(work), t2(work);
t1.join();
t2.join();
std::cout << counter << "\n";
return 0;
}ความเข้ากันได้ระหว่างทีแซนกับเอเอสแซน
ไม่สามารถใช้ทีแซนร่วมกับเอเอสแซนในโปรแกรมสร้างเดียวกันได้ (ทั้งสองขัดแย้งกัน) ให้ใช้การกำหนดค่าโปรแกรมสร้างแยกกัน โดยแบบหนึ่งใช้สำหรับเอเอสแซนร่วมกับยูบีแซน และอีกแบบใช้สำหรับทีแซน
เมทริกซ์โปรแกรมสร้างสำหรับตัวตรวจสอบ
การตั้งค่าการผสานรวมอย่างต่อเนื่องที่ใช้งานได้จริงจะเรียกใช้ชุดการทดสอบด้วยโปรแกรมสร้างที่มีตัวตรวจสอบสองแบบ
- โปรแกรมสร้าง A:
-fsanitize=address,undefined - โปรแกรมสร้าง B:
-fsanitize=thread
วิธีนี้ครอบคลุมข้อบกพร่องด้านหน่วยความจำ พฤติกรรมที่ไม่กำหนดไว้ และการทำงานพร้อมกัน
ต้นทุนและข้อจำกัด
ทีแซนอาจทำให้โปรแกรมช้าลง 5–15 เท่าและใช้หน่วยความจำเพิ่มขึ้นมาก เช่นเดียวกับตัวตรวจสอบทั้งหมด ทีแซนตรวจจับได้เฉพาะข้อบกพร่องบนเส้นทางของโค้ดที่ถูกเรียกใช้ ดังนั้นการทดสอบหลายเธรดที่ดีจึงสำคัญ
ตรวจสอบอย่างรวดเร็ว
ทบทวนว่าทีแซนตรวจจับอะไร
สรุปทบทวน
คุณได้เรียนรู้ยูบีแซนและทีแซน
- ยูบีแซน (
-fsanitize=undefined) ค้นหาค่าล้น การเลื่อนบิตผิด และการอ้างอิงตัวชี้ว่าง - ใช้
-fno-sanitize-recoverเพื่อยุติการทำงานเมื่อพบพฤติกรรมที่ไม่กำหนดไว้ครั้งแรก - ทีแซน (
-fsanitize=thread) ค้นหาการแย่งข้อมูล แก้ไขด้วยมิวเท็กซ์หรืออะตอมิก - ทีแซนและเอเอสแซนต้องใช้โปรแกรมสร้างแยกกัน
เรียนรู้ C++ ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 51
- บทเรียน
- 203
คำถามที่พบบ่อย
บทเรียน “UBSan และ TSan” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “UBSan และ TSan” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C++ Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C++ Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “UBSan และ TSan”
ค้นหาพฤติกรรมไม่กำหนดและการแข่งขัน คุณปฏิบัติ C++ Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C++ Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน C++ Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “UBSan และ TSan” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน C++ Academy นี้ได้ไหม
ได้ บทเรียน C++ Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การใช้ gdb และ lldb
- AddressSanitizer
- UBSan และ TSan
- พื้นฐาน Valgrind