Debug (โหมดดีบัก) — คือการกำหนดค่าบิลด์ของแอปพลิเคชันมือถือที่คอมไพเลอร์รวมข้อมูลสัญลักษณ์ ปิดการเพิ่มประสิทธิภาพโค้ด และเชื่อมต่อดีบักเกอร์สำหรับการวิเคราะห์การทำงานทีละขั้นตอน ตามข้อมูลจาก Android Developers บิลด์ Debug มีสัญลักษณ์ดีบัก ไม่บีบอัดทรัพยากร และอนุญาตให้เชื่อมต่อตัวตรวจสอบฐานข้อมูลและคำขอเครือข่าย โหมด Debug ตรงกันข้ามกับบิลด์ Release: ใน Debug นักพัฒนาเสียสละประสิทธิภาพเพื่อความโปร่งใสในการทำงานของโค้ด
ประเด็นสำคัญ
Debug ไม่ใช่แค่แฟล็กของคอมไพเลอร์ แต่เป็นชุดการตั้งค่าที่ทำให้แอปพลิเคชันโปร่งใสสำหรับนักพัฒนา ในโหมด Debug คอมไพเลอร์จะเพิ่มตารางชื่อสัญลักษณ์ (DWARF) ลงในไฟล์ปฏิบัติการ ซึ่งเชื่อมโยงโค้ดเครื่องกับบรรทัดซอร์สโค้ด หากไม่มีตารางนี้ ดีบักเกอร์จะไม่สามารถแสดงว่าบรรทัดใดของโค้ดกำลังทำงานอยู่ในขณะนั้น
ดีบักเกอร์ (debugger) คือโปรแกรมที่เรียกใช้แอปพลิเคชันของคุณในสภาพแวดล้อมที่ควบคุม คุณสามารถหยุดการทำงานที่บรรทัดใดก็ได้ (เบรกพอยน์) ดูค่าของตัวแปรทั้งหมดในขอบเขตปัจจุบัน เปลี่ยนแปลงได้ทันที และดำเนินการต่อ สำหรับแพลตฟอร์มมือถือ ดีบักเกอร์มาตรฐานคือ LLDB — ส่วนประกอบของ LLVM ที่ใช้ทั้งใน Xcode และ Android Studio
โหมด Debug ยังรวมถึง การตรวจสอบเพิ่มเติม ที่ปิดใช้งานใน Release: การยืนยัน (assertions) การตรวจสอบขอบเขตอาร์เรย์ ตัวตรวจจับการรั่วไหลของหน่วยความจำ และการบันทึกที่ครอบคลุม การตรวจสอบเหล่านี้ทำให้แอปพลิเคชันช้าลงแต่ตรวจจับข้อผิดพลาดได้ในขั้นตอนแรกของการพัฒนา — ก่อนที่โค้ดจะถึงมือผู้ใช้
ความแตกต่างระหว่าง บิลด์ Debug และ Release นั้นพื้นฐาน: มันคือชุดแฟล็กของคอมไพเลอร์ การกำหนดค่าลงนาม และการตั้งค่าแพ็คเกจที่แตกต่างกันสองชุด การเข้าใจความแตกต่างเหล่านี้ช่วยหลีกเลี่ยงสถานการณ์ที่ “ทำงานในซิมิวเลเตอร์แต่ไม่ทำงานบนอุปกรณ์จริง”
| พารามิเตอร์ | Debug | Release |
|---|---|---|
| การเพิ่มประสิทธิภาพ | ปิด (-O0) | เปิด (-Os หรือ -O2) |
| สัญลักษณ์ | ตาราง DWARF เต็ม | ถูกลบ |
| การลงนาม | ใบรับรองการพัฒนา | ใบรับรองการเผยแพร่ |
| โปรไฟล์ | โปรไฟล์การจัดเตรียม Debug | โปรไฟล์ App Store / Ad Hoc |
| การบันทึก | เต็ม (ทุกระดับ) | ปิดหรือน้อยที่สุด |
| การทำให้สับสน | ปิด | เปิด (ProGuard/R8) |
| ขนาด .apk/.ipa | ใหญ่กว่า (สัญลักษณ์ + ไม่บีบอัด) | เล็กกว่า (R8 + ทรัพยากร) |
บิลด์ Debug ใช้ในทุกขั้นตอนของการพัฒนาและการทดสอบบนอุปกรณ์ท้องถิ่น บิลด์ Release ถูกสร้างก่อนส่งไปยัง App Store Connect หรือ Google Play Console การดีบักบนบิลด์ Release เป็นไปได้ทางเทคนิคแต่ไม่สะดวกอย่างยิ่งเนื่องจากเมธอดที่ถูกเปลี่ยนชื่อ (R8) และการขาด symbolication สำหรับบันทึกการขัดข้อง
ปัญหาที่พบบ่อย คือโค้ดที่ทำงานใน Debug แต่ขัดข้องใน Release สาเหตุคือ UB (พฤติกรรมที่ไม่กำหนด) ในโค้ดที่คอมไพเลอร์จัดการแตกต่างกันด้วยระดับการเพิ่มประสิทธิภาพที่ต่างกัน ตัวอย่างทั่วไป: การอ่านตัวแปรที่ไม่ได้เริ่มต้นหรือการละเมิด strict aliasing เพื่อตรวจจับข้อผิดพลาดเหล่านี้ ให้ใช้เครื่องมือวิเคราะห์แบบคงที่ (Clang Static Analyzer, ktlint) ก่อนแต่ละบิลด์ Release
LLDB คือดีบักเกอร์ประสิทธิภาพสูงที่สร้างบน LLVM รองรับ C, C++, Objective-C, Swift และ Kotlin/Native LLDB มีอินเทอร์เฟซ REPL ที่คุณสามารถดำเนินการนิพจน์ใดก็ได้ เปลี่ยนค่าตัวแปร และเรียกใช้ฟังก์ชันในบริบทของแอปพลิเคชันที่หยุดไว้
เบรกพอยน์ คือเครื่องมือหลักของดีบักเกอร์ คุณวางจุดบนบรรทัดของโค้ด และแอปพลิเคชันจะหยุดเมื่อการทำงานถึงบรรทัดนั้น LLDB รองรับเบรกพอยน์หลายประเภท: แบบมีเงื่อนไข (ทำงานเมื่อเงื่อนไขเป็นจริงเท่านั้น) แบบสัญลักษณ์ (เมื่อเรียกฟังก์ชัน) และแบบครั้งเดียว (ทำงานครั้งเดียวและถูกลบโดยอัตโนมัติ)
วอตช์พอยน์ คือจุดสังเกตการเปลี่ยนแปลงของตัวแปร คุณระบุที่อยู่หน่วยความจำ และดีบักเกอร์หยุดการทำงานเมื่อมีการเขียนไปยังที่อยู่นั้น เครื่องมือนี้จำเป็นสำหรับการค้นหาการแข่งขันของข้อมูลและการกลายพันธุ์ที่ไม่ถูกต้องของออบเจกต์ที่ใช้ร่วมกัน หากต้องการดูลำดับชั้น UIKit ให้ใช้ UIView Inspector ที่มีใน Xcode
// การตั้งค่าเบรกพอยน์แบบมีเงื่อนไข
(lldb) breakpoint set --name "viewDidLoad" --condition "self.isViewLoaded == false"
// วอตช์พอยน์บนคุณสมบัติ
(lldb) watchpoint set variable self->_loadingState
// ดำเนินการโค้ดในบริบทที่หยุด
(lldb) expr self.view.backgroundColor = UIColor.redColor
IDE ทั้งสองมี ตัวตรวจสอบแบบกราฟิก บน LLDB Android Studio ประกอบด้วย Layout Inspector (ลำดับชั้น View), Network Inspector (การติดตามคำขอ HTTP) และ Database Inspector (SQLite แบบเรียลไทม์) Xcode มี Debug Memory Graph (การวิเคราะห์การรั่วไหลของหน่วยความจำ) และ View Debugger (มุมมอง 3 มิติของเลเยอร์ UIKit)
ตั้งแต่ Android 11 เป็นต้นไป การดีบักผ่าน Wi-Fi ทำงานโดยไม่ต้องเชื่อมต่อ USB: เพียงสแกน QR Code จาก Android Studio iOS รองรับการดีบัก Wi-Fi ตั้งแต่ Xcode 9+ — อุปกรณ์เชื่อมต่อผ่าน USB หนึ่งครั้ง หลังจากนั้นเซสชันดีบักสามารถทำงานผ่านเครือข่ายได้ การดีบัก Wi-Fi ไม่เหมาะสำหรับเซิร์ฟเวอร์ CI เนื่องจากความหน่วงที่คาดเดาไม่ได้และการสูญเสียแพ็กเกต ดังนั้นไปป์ไลน์อัตโนมัติจึงใช้ USB เสมอ อย่างไรก็ตาม สำหรับการพัฒนาในเครื่อง การดีบัก Wi-Fi สะดวกกว่าอย่างเห็นได้ชัด — นักพัฒนาไม่ถูกผูกติดกับสายเคเบิลและสามารถทดสอบแอปพลิเคชันบนอุปกรณ์ที่อยู่อีกด้านหนึ่งของห้อง
Android Debug Bridge (ADB) คือเครื่องมืออเนกประสงค์สำหรับโต้ตอบกับอุปกรณ์ Android จากบรรทัดคำสั่ง ผ่าน ADB คุณสามารถติดตั้งแอปพลิเคชัน เริ่มการดีบัก คัดลอกไฟล์ ดำเนินการคำสั่ง shell และดูบันทึก Android Studio ใช้ ADB เบื้องหลังสำหรับการดำเนินการดีบักทั้งหมด
Android Studio รองรับสองโหมดดีบัก: Run (เปิดใช้ปกติ) และ Debug (เปิดใช้พร้อมดีบักเกอร์ที่เชื่อมต่อ) ในโหมด Debug คุณสามารถตั้งค่าเบรกพอยน์ในตัวแก้ไข ดูตัวแปรในหน้าต่าง Debug Tool และประเมินนิพจน์ใน Evaluate Expression หากต้องการดีบักกระบวนการพื้นหลัง (Service, BroadcastReceiver) ให้ใช้ Attach Debugger to Android Process
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// เบรกพอยน์ที่นี่จะหยุดการทำงาน
val button = findViewById<Button>(R.id.btn_debug)
button.setOnClickListener {
startDebugProcess()
}
}
private fun startDebugProcess() {
val data = fetchDataFromApi()
Log.d("Debug", "Data loaded: $data")
}
}
คำสั่ง ADB shell ให้เข้าถึงระบบไฟล์ของอุปกรณ์โดยไม่ต้องมีสิทธิ์ root คุณสามารถดูเนื้อหาของไดเรกทอรี databases คัดลอกไฟล์ .db ไปยังคอมพิวเตอร์ของคุณและเปิดด้วยไคลเอนต์ SQLite ใดก็ได้ Android Studio Database Inspector ทำให้กระบวนการนี้เป็นอัตโนมัติ: คุณเห็นข้อมูลฐานข้อมูลสดแบบเรียลไทม์และสามารถดำเนินการคำสั่ง SQL ได้โดยตรงจาก IDE
Xcode มีสภาพแวดล้อมการดีบักแบบบูรณาการที่สร้างบน LLDB นักพัฒนาสามารถเรียกใช้แอปพลิเคชันบนซิมิวเลเตอร์หรืออุปกรณ์จริง ตั้งค่าเบรกพอยน์ และใช้ Debug Navigator เพื่อควบคุมเธรดการทำงาน แตกต่างจาก Android ตรงที่ iOS ไม่อนุญาตให้เรียกใช้บิลด์ Debug สองตัวพร้อมกันบนอุปกรณ์เดียวกันโดยไม่มีการกำหนดค่าพิเศษ
ซิมิวเลเตอร์ เรียกใช้แอปพลิเคชันเป็นกระบวนการ macOS ดั้งเดิม ซึ่งให้วงจรการดีบักที่เร็วที่สุด บนอุปกรณ์จริง การดีบักเกิดขึ้นผ่าน USB หรือ Wi-Fi (ตั้งแต่ iOS 16) และ LLDB สื่อสารกับ debugserver บนอุปกรณ์ ประสิทธิภาพการดีบักบนอุปกรณ์ต่ำกว่าเนื่องจากแบนด์วิดท์ที่จำกัดของ USB 2.0 แต่มีเพียงอุปกรณ์จริงเท่านั้นที่ให้ทดสอบสถานการณ์จริง: การแจ้งเตือนแบบพุช กล้อง เซ็นเซอร์
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
}
private func setupUI() {
let label = UILabel()
label.text = "โหมดดีบัก"
label.textColor = .systemBlue
view.addSubview(label)
}
}
Xcode Organizer รวบรวมบันทึกการขัดข้องจากอุปกรณ์ของผู้ทดสอบผ่าน Crash Logs สำหรับการ symbolication (การแปลงที่อยู่เป็นชื่อฟังก์ชัน) จำเป็นต้องใช้ไฟล์ .dSYM ซึ่งถูกสร้างขึ้นกับทุกบิลด์ Debug ในบิลด์ Release dSYM ก็ถูกสร้างเช่นกัน แต่บันทึกการขัดข้องจาก App Store จะต้องอัปโหลดไปยัง Organizer ด้วยตนเองหรือผ่านบริการ bitcode
คำถามที่พบบ่อย
ในทางเทคนิค ได้ — ผ่านการเผยแพร่ Ad Hoc ด้วยใบรับรอง Debug แต่ Apple และ Google ไม่แนะนำ บิลด์ Debug มีสัญลักษณ์ดีบักและประสิทธิภาพต่ำ ซึ่งทำให้ประสบการณ์ผู้ใช้แย่ลงและเพิ่มขนาดแอปพลิเคชัน 2–3 เท่า
สาเหตุ คือการเพิ่มประสิทธิภาพของคอมไพเลอร์ที่ปิดอยู่ (-O0) คอมไพเลอร์ไม่ inline ฟังก์ชัน ไม่ลบโค้ดที่ตายแล้ว และเก็บตัวแปรกลางทั้งหมดไว้ นอกจากนี้ Debug ยังรวมการตรวจสอบการยืนยันและขอบเขตอาร์เรย์ที่ไม่มีใน Release
ใน Xcode เลือก Window → Devices and Simulators ทำเครื่องหมาย “Connect via network” สำหรับอุปกรณ์ของคุณ อุปกรณ์และ Mac ต้องอยู่ในเครือข่าย Wi-Fi เดียวกัน หลังจากเชื่อมต่อผ่าน USB หนึ่งครั้ง การดีบักจะทำงานผ่าน Wi-Fi ในการเปิดใช้ครั้งต่อๆ ไป
Attach to process ช่วยให้คุณเชื่อมต่อดีบักเกอร์กับกระบวนการที่กำลังทำงานอยู่แล้วโดยไม่ต้องรีสตาร์ทแอปพลิเคชัน ซึ่งมีประโยชน์สำหรับการดีบัก Service, BroadcastReceiver หรือกระบวนการที่เริ่มโดยเหตุการณ์ระบบ ซึ่งไม่สามารถใช้ Debug Run มาตรฐานได้
NSLog และ print โดยค่าเริ่มต้นจะแสดงบันทึกเฉพาะในการกำหนดค่า Debug เท่านั้น สำหรับ Release ให้ใช้ os_log กับแฟล็ก OSLogType.default — มันบันทึกข้อความใน Unified Logging System และสามารถเข้าถึงได้ผ่าน Console.app บน Mac
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม