Debug trong phát triển di động — bản chất, chế độ gỡ lỗi và cách hoạt động

Tác giả: IT Sectr Đã đăng: 2026-05-06 Thời gian đọc: 8 phút

Debug (chế độ gỡ lỗi) — là một cấu hình xây dựng ứng dụng di động trong đó trình biên dịch bao gồm thông tin ký hiệu, tắt tối ưu hóa mã và kết nối trình gỡ lỗi để phân tích thực thi từng bước. Theo Android Developers, bản dựng Debug chứa các ký hiệu gỡ lỗi, không nén tài nguyên và cho phép kết nối trình kiểm tra cơ sở dữ liệu và yêu cầu mạng. Chế độ Debug đối lập với bản dựng Release: trong Debug, nhà phát triển hy sinh hiệu suất để có sự minh bạch trong thực thi mã.

Những điểm chính

  • Debug — cấu hình xây dựng với thông tin gỡ lỗi, tối ưu hóa bị tắt và quyền truy cập trình gỡ lỗi
  • Trình gỡ lỗi cho phép đặt điểm dừng, xem biến và thực thi mã từng bước
  • Bản dựng Debug được ký bằng chứng chỉ gỡ lỗi và không thể xuất bản lên cửa hàng ứng dụng
  • LLDB là trình gỡ lỗi chính cho iOS/macOS và LLDB trong Android Studio cho Android
  • Hiệu suất của bản dựng Debug thấp hơn Release do thiếu tối ưu hóa trình biên dịch

Bản chất của chế độ Debug trong phát triển di động

Debug không chỉ là một cờ trình biên dịch, mà là một tập hợp đầy đủ các cài đặt giúp ứng dụng trở nên minh bạch cho nhà phát triển. Trong chế độ Debug, trình biên dịch thêm một bảng tên ký hiệu (DWARF) vào tệp thực thi, liên kết mã máy với các dòng mã nguồn. Không có bảng này, trình gỡ lỗi không thể hiển thị dòng mã nào đang được thực thi tại thời điểm hiện tại.

Trình gỡ lỗi (debugger) là một chương trình chạy ứng dụng của bạn trong môi trường được kiểm soát. Bạn có thể tạm dừng thực thi tại bất kỳ dòng nào (breakpoint), xem giá trị của tất cả các biến trong phạm vi hiện tại, thay đổi chúng khi đang chạy và tiếp tục thực thi. Đối với nền tảng di động, trình gỡ lỗi tiêu chuẩn là LLDB — một thành phần LLVM được sử dụng trong cả Xcode và Android Studio.

Chế độ Debug cũng bao gồm các kiểm tra bổ sung bị tắt trong Release: xác nhận (assertions), kiểm tra ranh giới mảng, trình phát hiện rò rỉ bộ nhớ và ghi nhật ký mở rộng. Các kiểm tra này làm chậm ứng dụng nhưng phát hiện lỗi ở giai đoạn đầu phát triển — trước khi mã đến tay người dùng.

Debug và Release: sự khác biệt chính giữa các bản dựng

Sự khác biệt giữa bản dựng Debug và Release là cơ bản: chúng là hai bộ cờ trình biên dịch, cấu hình ký và cài đặt đóng gói khác nhau. Hiểu những khác biệt này giúp tránh các tình huống “chạy được trên trình mô phỏng nhưng không chạy được trên thiết bị thật”.

Tham sốDebugRelease
Tối ưu hóaTắt (-O0)Bật (-Os hoặc -O2)
Ký hiệuBảng DWARF đầy đủĐã xóa
Chữ kýChứng chỉ phát triểnChứng chỉ phân phối
Hồ sơHồ sơ cấp phép DebugHồ sơ App Store / Ad Hoc
Ghi nhật kýĐầy đủ (tất cả cấp độ)Tắt hoặc tối thiểu
Làm rối mãTắtBật (ProGuard/R8)
Kích thước .apk/.ipaLớn hơn (ký hiệu + không nén)Nhỏ hơn (R8 + tài nguyên)

Khi nào sử dụng loại nào

Bản dựng Debug được sử dụng ở tất cả các giai đoạn phát triển và thử nghiệm trên thiết bị cục bộ. Bản dựng Release được tạo trước khi gửi lên App Store Connect hoặc Google Play Console. Gỡ lỗi trên bản dựng Release về mặt kỹ thuật có thể nhưng cực kỳ bất tiện do các phương thức bị đổi tên (R8) và thiếu symbolication cho nhật ký sự cố.

Vấn đề khi chuyển đổi chế độ

Một vấn đề phổ biến là mã hoạt động trong Debug nhưng bị lỗi trong Release. Nguyên nhân là UB (hành vi không xác định) trong mã mà trình biên dịch xử lý khác nhau với các mức tối ưu hóa khác nhau. Một ví dụ điển hình: đọc biến chưa được khởi tạo hoặc vi phạm strict aliasing. Để phát hiện các lỗi này, hãy sử dụng trình phân tích tĩnh (Clang Static Analyzer, ktlint) trước mỗi bản dựng Release.

Công cụ gỡ lỗi: LLDB, điểm dừng và trình kiểm tra

LLDB là trình gỡ lỗi hiệu suất cao dựa trên LLVM, hỗ trợ C, C++, Objective-C, Swift và Kotlin/Native. LLDB cung cấp giao diện REPL nơi bạn có thể thực thi các biểu thức tùy ý, thay đổi giá trị biến và gọi hàm trong ngữ cảnh của ứng dụng bị tạm dừng.

Điểm dừng và các loại

Breakpoint là công cụ chính của trình gỡ lỗi. Bạn đặt một điểm trên một dòng mã và ứng dụng sẽ tạm dừng khi thực thi đến dòng đó. LLDB hỗ trợ nhiều loại breakpoint: có điều kiện (chỉ kích hoạt khi điều kiện được đáp ứng), ký hiệu (khi gọi hàm) và một lần (kích hoạt một lần và tự động bị xóa).

Watchpoint và trình kiểm tra bộ nhớ

Watchpoint là điểm quan sát sự thay đổi của biến. Bạn chỉ định một địa chỉ bộ nhớ và trình gỡ lỗi tạm dừng thực thi khi có bất kỳ ghi nào vào địa chỉ đó. Công cụ này không thể thiếu khi tìm kiếm các cuộc đua dữ liệu và biến đổi sai của các đối tượng dùng chung. Để xem hệ thống phân cấp UIKit, hãy sử dụng UIView Inspector có trong Xcode.

lldb
// Đặt breakpoint có điều kiện
(lldb) breakpoint set --name "viewDidLoad" --condition "self.isViewLoaded == false"

// Watchpoint trên thuộc tính
(lldb) watchpoint set variable self->_loadingState

// Thực thi mã trong ngữ cảnh bị dừng
(lldb) expr self.view.backgroundColor = UIColor.redColor

Trình kiểm tra Xcode và Android Studio

Cả hai IDE đều cung cấp trình kiểm tra đồ họa trên nền LLDB. Android Studio bao gồm Layout Inspector (hệ thống phân cấp View), Network Inspector (theo dõi yêu cầu HTTP) và Database Inspector (SQLite thời gian thực). Xcode cung cấp Debug Memory Graph (phân tích rò rỉ bộ nhớ) và View Debugger (xem 3D các lớp UIKit).

Gỡ lỗi từ xa và gỡ lỗi qua Wi-Fi

Từ Android 11, gỡ lỗi qua Wi-Fi hoạt động mà không cần kết nối USB: chỉ cần quét mã QR từ Android Studio. iOS hỗ trợ gỡ lỗi Wi-Fi từ Xcode 9+ — thiết bị kết nối một lần qua USB, sau đó các phiên gỡ lỗi có thể chạy qua mạng. Gỡ lỗi Wi-Fi không phù hợp cho máy chủ CI do độ trễ không thể đoán trước và mất gói tin, vì vậy các đường ống tự động luôn sử dụng USB. Tuy nhiên, đối với phát triển cục bộ, gỡ lỗi Wi-Fi thuận tiện hơn đáng kể — nhà phát triển không bị ràng buộc bởi cáp và có thể thử nghiệm ứng dụng trên thiết bị ở đầu kia của căn phòng.

Debug trên Android: Android Studio và gỡ lỗi qua ADB

Android Debug Bridge (ADB) là một công cụ phổ quát để tương tác với thiết bị Android từ dòng lệnh. Qua ADB, bạn có thể cài đặt ứng dụng, bắt đầu gỡ lỗi, sao chép tệp, thực thi lệnh shell và xem nhật ký. Android Studio sử dụng ADB nội bộ cho tất cả các hoạt động gỡ lỗi.

Kết nối trình gỡ lỗi trong Android Studio

Android Studio hỗ trợ hai chế độ gỡ lỗi: Run (khởi chạy bình thường) và Debug (khởi chạy với trình gỡ lỗi được kết nối). Trong chế độ Debug, bạn có thể đặt breakpoint trực tiếp trong trình soạn thảo, xem biến trong cửa sổ Debug Tool và đánh giá biểu thức trong Evaluate Expression. Để gỡ lỗi các tiến trình nền (Service, BroadcastReceiver), hãy sử dụng Attach Debugger to Android Process.

kotlin
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Breakpoint ở đây sẽ tạm dừng thực thi
        val button = findViewById<Button>(R.id.btn_debug)
        button.setOnClickListener {
            startDebugProcess()
        }
    }

    private fun startDebugProcess() {
        val data = fetchDataFromApi()
        Log.d("Debug", "Data loaded: $data")
    }
}

Shell ADB và kiểm tra cơ sở dữ liệu

Các lệnh shell ADB cung cấp quyền truy cập vào hệ thống tệp của thiết bị mà không cần quyền root. Bạn có thể xem nội dung của thư mục databases, sao chép tệp .db vào máy tính và mở nó bằng bất kỳ máy khách SQLite nào. Android Studio Database Inspector tự động hóa quy trình này: bạn thấy dữ liệu cơ sở dữ liệu trực tiếp theo thời gian thực và có thể thực thi truy vấn SQL trực tiếp từ IDE.

Debug trên iOS: Xcode, trình gỡ lỗi và chẩn đoán

Xcode cung cấp môi trường gỡ lỗi tích hợp dựa trên LLDB. Nhà phát triển có thể chạy ứng dụng trên trình mô phỏng hoặc thiết bị vật lý, đặt breakpoint và sử dụng Debug Navigator để kiểm soát các luồng thực thi. Không giống như Android, iOS không cho phép chạy hai bản dựng Debug đồng thời trên cùng một thiết bị mà không có cấu hình đặc biệt.

Gỡ lỗi trên trình mô phỏng và thiết bị

Trình mô phỏng chạy ứng dụng như một tiến trình macOS gốc, cung cấp chu kỳ gỡ lỗi nhanh nhất. Trên thiết bị vật lý, gỡ lỗi diễn ra qua USB hoặc Wi-Fi (từ iOS 16) và LLDB giao tiếp với debugserver trên thiết bị. Hiệu suất gỡ lỗi trên thiết bị thấp hơn do băng thông USB 2.0 hạn chế, nhưng chỉ có thiết bị vật lý mới cho phép thử nghiệm các kịch bản thực tế: thông báo đẩy, máy ảnh, cảm biến.

swift
import UIKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
    }

    private func setupUI() {
        let label = UILabel()
        label.text = "Chế độ Debug"
        label.textColor = .systemBlue
        view.addSubview(label)
    }
}

Chẩn đoán và báo cáo sự cố

Xcode Organizer thu thập nhật ký sự cố từ thiết bị của người thử nghiệm qua Crash Logs. Để symbolication (chuyển đổi địa chỉ thành tên hàm), cần có tệp .dSYM, được tạo ra với mỗi bản dựng Debug. Trong bản dựng Release, dSYM cũng được tạo, nhưng nhật ký sự cố từ App Store cần được tải lên Organizer thủ công hoặc qua dịch vụ bitcode.

Các câu hỏi thường gặp

Có thể chạy bản dựng Debug trên thiết bị của người dùng không?

Về mặt kỹ thuật có — thông qua phân phối Ad Hoc với chứng chỉ Debug, nhưng Apple và Google không khuyến nghị điều này. Bản dựng Debug chứa các ký hiệu gỡ lỗi và hiệu suất thấp hơn, làm giảm trải nghiệm người dùng và tăng kích thước ứng dụng lên 2–3 lần.

Tại sao bản dựng Debug chạy chậm hơn Release?

Nguyên nhân là tối ưu hóa trình biên dịch bị tắt (-O0). Trình biên dịch không inline các hàm, không loại bỏ mã chết và giữ lại tất cả các biến trung gian. Ngoài ra, Debug bao gồm các kiểm tra xác nhận và ranh giới mảng mà không có trong Release.

Làm thế nào để thiết lập gỡ lỗi Wi-Fi cho iOS?

Trong Xcode chọn Window → Devices and Simulators, đánh dấu “Connect via network” cho thiết bị của bạn. Thiết bị và Mac phải ở trên cùng một mạng Wi-Fi. Sau khi kết nối qua USB một lần, gỡ lỗi sẽ hoạt động qua Wi-Fi trong các lần khởi chạy tiếp theo.

“Attach to process” trong Android Studio là gì?

Attach to process cho phép bạn kết nối trình gỡ lỗi với một tiến trình đang chạy mà không cần khởi động lại ứng dụng. Điều này hữu ích để gỡ lỗi Service, BroadcastReceiver hoặc các tiến trình được khởi động bởi sự kiện hệ thống, nơi Debug Run tiêu chuẩn không áp dụng được.

Làm thế nào để xem NSLog và print trong bản dựng Release?

NSLog và print theo mặc định chỉ xuất nhật ký trong cấu hình Debug. Đối với Release, hãy sử dụng os_log với cờ OSLogType.default — nó lưu thông báo vào Unified Logging System và có thể truy cập qua Console.app trên Mac.

Tổng kết

  • Bản dựng Debug bao gồm các ký hiệu gỡ lỗi, tắt tối ưu hóa và sử dụng chứng chỉ ký phát triển
  • LLDB là trình gỡ lỗi chính cho cả hai nền tảng, hỗ trợ breakpoint, watchpoint và REPL
  • Sự khác biệt giữa Debug và Release ảnh hưởng đến tối ưu hóa, ký hiệu, chữ ký, làm rối mã và kích thước bản dựng
  • ADB cho Android và debugserver cho iOS cung cấp giao tiếp IDE-thiết bị
  • Hiệu suất của bản dựng Debug thấp hơn 2–5 lần do tối ưu hóa bị tắt
  • Nhật ký sự cố trong bản dựng Debug chứa tên hàm có thể đọc được; Release yêu cầu symbolication qua dSYM

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm