Mở rộng Trình kiểm tra bộ nhớ để gỡ lỗi C/C++

Trong Chrome 92, chúng tôi đã ra mắt Trình kiểm tra bộ nhớ, một công cụ để kiểm tra vùng đệm bộ nhớ tuyến tính. Trong bài viết này, chúng ta sẽ thảo luận về cách cải thiện Trình kiểm tra để gỡ lỗi C/C++ và những thách thức kỹ thuật gặp phải trong quá trình này.

Dưới đây là một số bài đăng trên blog có liên quan nếu bạn mới sử dụng tính năng gỡ lỗi C/C++ và Trình kiểm tra bộ nhớ:

Giới thiệu

Trình kiểm tra bộ nhớ cung cấp cho bạn các tuỳ chọn gỡ lỗi mạnh mẽ hơn cho vùng đệm bộ nhớ tuyến tính. Trong trường hợp C/C++, bạn có thể kiểm tra các đối tượng bộ nhớ C/C++ trong Bộ nhớ WebAssembly.

Việc nhận dạng các byte của đối tượng trong bộ nhớ WebAssembly xung quanh là một điểm khó khăn. Bạn phải biết kích thước của đối tượng và đếm số byte từ đầu đối tượng. Trong ảnh chụp màn hình bên dưới, byte đầu tiên của mảng int32 gồm 10 phần tử được chọn nhưng không rõ những byte nào khác thuộc về mảng này. Sẽ thật tuyệt nếu bạn có thể nhận ra ngay tất cả các byte thuộc về đối tượng.

Ảnh chụp màn hình của trình kiểm tra bộ nhớ ban đầu với một byte được làm nổi bật

Làm nổi bật đối tượng trong Trình kiểm tra bộ nhớ

Kể từ Chrome 107, Trình kiểm tra bộ nhớ sẽ làm nổi bật tất cả các byte của đối tượng bộ nhớ C/C++. Điều này giúp bạn phân biệt các vùng nhớ này với bộ nhớ xung quanh.

Ảnh chụp màn hình của trình kiểm tra bộ nhớ đã cập nhật với một mảng được làm nổi bật rực rỡ

Hãy xem video dưới đây để thấy Trình kiểm tra bộ nhớ hoạt động. Khi bạn hiển thị mảng x trong Trình kiểm tra bộ nhớ, bộ nhớ được làm nổi bật sẽ xuất hiện trong Trình xem bộ nhớ cùng với một khối mới ngay phía trên. Khối này nhắc bạn tên và loại bộ nhớ được làm nổi bật. Nhấp vào khối này để chuyển đến bộ nhớ của đối tượng. Nếu bạn di chuột qua khối, một biểu tượng dấu thập sẽ xuất hiện – hãy nhấp vào biểu tượng đó để xoá phần được làm nổi bật.

Khi bạn chọn một byte nằm ngoài đối tượng mà bạn kiểm tra, phần đánh dấu sẽ mất tiêu điểm để tránh làm bạn mất tập trung. Để lấy nét lại, hãy nhấp lại vào bất kỳ byte nào của đối tượng hoặc vào khối.

Tính năng hỗ trợ làm nổi bật đối tượng không chỉ giới hạn ở các mảng. Bạn cũng có thể kiểm tra cấu trúc, đối tượng và con trỏ. Những thay đổi này giúp bạn dễ dàng khám phá bộ nhớ của ứng dụng C/C++ hơn bao giờ hết!

Bạn có muốn dùng thử không? Bạn sẽ cần:

  • Có Chrome 107 trở lên.
  • Cài đặt Tiện ích DWARF C/C++.
  • Bật tính năng gỡ lỗi DWARF trong DevTools > Cài đặt. Settings (Cài đặt) > Experiments (Thử nghiệm) > WebAssemble Debugging: Enable DWARF support (Gỡ lỗi WebAssemble: Bật tính năng hỗ trợ DWARF).
  • Mở trang minh hoạ này.
  • Làm theo hướng dẫn trên trang.

Ví dụ về gỡ lỗi

Trong phần này, hãy xem một lỗi đồ chơi để minh hoạ cách bạn có thể sử dụng Trình kiểm tra bộ nhớ để gỡ lỗi C/C++. Trong mã mẫu bên dưới, lập trình viên tạo một mảng số nguyên và quyết định sử dụng phép tính con trỏ để chọn phần tử cuối cùng. Rất tiếc, lập trình viên đã mắc lỗi trong quá trình tính toán con trỏ và giờ đây, thay vì in phần tử cuối cùng, chương trình sẽ in các giá trị vô nghĩa.

#include <iostream>

int main()
{
    int numbers[] = {1, 2, 3, 4};
    int *ptr = numbers;
    int arraySize = sizeof(numbers)/sizeof(int);
    int* lastNumber = ptr + arraySize;  // Can you notice the bug here?
    std::cout <<../ *lastNumber <<../ '\n';
    return 0;
}

Lập trình viên chuyển sang Trình kiểm tra bộ nhớ để gỡ lỗi vấn đề. Bạn có thể làm theo bản minh hoạ này! Trước tiên, họ kiểm tra mảng trong Trình kiểm tra bộ nhớ và thấy rằng mảng numbers chỉ chứa các số nguyên 1, 2, 34 như dự kiến.

Ảnh chụp màn hình của trình kiểm tra bộ nhớ đã mở với một mảng int32 đã kiểm tra. Tất cả phần tử mảng đều được làm nổi bật.

Tiếp theo, họ sẽ hiển thị biến lastNumber từ ngăn Phạm vi và lưu ý rằng con trỏ trỏ đến một số nguyên bên ngoài mảng! Với kiến thức này, lập trình viên nhận ra rằng họ đã tính sai độ dời con trỏ ở dòng 8. Giá trị này phải là ptr + arraySize - 1.

Ảnh chụp màn hình của trình kiểm tra bộ nhớ đã mở cho thấy bộ nhớ được đánh dấu được con trỏ có tên &quot;lastNumber&quot; trỏ đến. Bộ nhớ được đánh dấu nằm ngay sau byte cuối cùng của mảng được đánh dấu trước đó.

Mặc dù đây là ví dụ về đồ chơi, nhưng nó minh hoạ cách làm nổi bật đối tượng truyền tải hiệu quả kích thước và vị trí của các đối tượng bộ nhớ, giúp bạn hiểu rõ hơn về những gì đang diễn ra bên trong bộ nhớ của ứng dụng C/C++.

Cách Công cụ cho nhà phát triển xác định nội dung cần làm nổi bật

Trong phần này, chúng ta sẽ xem xét hệ sinh thái công cụ hỗ trợ gỡ lỗi C/C++. Cụ thể, bạn sẽ tìm hiểu cách DevTools, V8, Tiện ích DWARF C/C++ và Emscripten giúp gỡ lỗi C/C++ trong Chrome.

Để khai thác tối đa tính năng gỡ lỗi C/C++ trong DevTools, bạn cần có hai điều:

  • Tiện ích C/C++ DWARF đã cài đặt trong Chrome
  • Các tệp nguồn C/C++ được biên dịch sang WebAssembly bằng trình biên dịch Emscripten mới nhất theo hướng dẫn trong bài đăng trên blog này

Nhưng tại sao? V8 , công cụ JavaScript và WebAssembly của Chrome, không biết cách thực thi C hoặc C++. Nhờ Emscripten, một trình biên dịch C/C++ sang WebAssembly, bạn có thể biên dịch các ứng dụng được tạo bằng C hoặc C++ dưới dạng WebAssembly và thực thi các ứng dụng đó trong trình duyệt!

Trong quá trình biên dịch, emscripten sẽ nhúng dữ liệu gỡ lỗi DWARF vào tệp nhị phân của bạn. Nói chung, dữ liệu này giúp tiện ích xác định những biến WebAssembly tương ứng với biến C/C++ của bạn, v.v. Bằng cách này, DevTools có thể hiển thị cho bạn các biến C++ mặc dù V8 thực sự đang chạy WebAssembly. Nếu bạn tò mò, hãy xem bài đăng trên blog này để biết ví dụ về dữ liệu gỡ lỗi DWARF.

Vậy điều gì thực sự xảy ra khi bạn hiển thị lastNumber? Ngay khi bạn nhấp vào biểu tượng bộ nhớ, DevTools sẽ kiểm tra xem bạn muốn kiểm tra biến nào. Sau đó, trình bổ trợ này truy vấn tiện ích về loại dữ liệu và vị trí của lastNumber. Ngay khi tiện ích phản hồi bằng thông tin đó, Trình kiểm tra bộ nhớ có thể hiển thị lát cắt bộ nhớ có liên quan và biết loại của lát cắt đó, cũng như cho bạn biết kích thước của đối tượng.

Nếu xem lastNumber trong ví dụ trước, bạn có thể nhận thấy rằng chúng ta đã kiểm tra lastNumber: int *, nhưng khối trong Trình kiểm tra bộ nhớ cho biết *lastNumber: int, điều gì đã xảy ra? Trình kiểm tra sử dụng tính năng tham chiếu con trỏ kiểu C++ để cho biết loại đối tượng hiển thị với bạn! Nếu bạn kiểm tra con trỏ, trình kiểm tra sẽ cho bạn biết con trỏ trỏ đến đâu.

Duy trì các điểm nổi bật trên các bước của trình gỡ lỗi

Khi bạn hiển thị một đối tượng trong Trình kiểm tra bộ nhớ và thực hiện bước với trình gỡ lỗi, Trình kiểm tra sẽ duy trì trạng thái làm nổi bật nếu cho rằng trạng thái đó vẫn có thể áp dụng. Ban đầu, chúng tôi không có tính năng này trong lộ trình phát triển, nhưng nhanh chóng nhận ra rằng điều này ảnh hưởng đến trải nghiệm gỡ lỗi của bạn. Hãy tưởng tượng bạn phải kiểm tra lại mảng sau mỗi bước như trong video bên dưới!

Khi trình gỡ lỗi gặp một điểm ngắt mới, Trình kiểm tra bộ nhớ sẽ truy vấn lại V8 và phần mở rộng cho biến được liên kết với phần đánh dấu trước đó. Sau đó, hàm này so sánh vị trí và loại của các đối tượng. Nếu các từ đó khớp nhau, thì phần được làm nổi bật sẽ vẫn xuất hiện. Trong video ở trên, có một vòng lặp for ghi vào mảng x. Các thao tác này không thay đổi loại hoặc vị trí của mảng, vì vậy, mảng vẫn được làm nổi bật.

Bạn có thể thắc mắc điều này ảnh hưởng như thế nào đến con trỏ. Nếu bạn có một con trỏ được làm nổi bật và chỉ định lại con trỏ đó cho một đối tượng khác, thì vị trí cũ và mới của các đối tượng được làm nổi bật sẽ khác nhau và phần làm nổi bật sẽ biến mất. Vì đối tượng mới được trỏ đến có thể nằm ở bất kỳ vị trí nào trong Bộ nhớ WebAssembly và có thể sẽ ít liên quan đến vị trí bộ nhớ trước đó, nên việc xoá phần đánh dấu sẽ rõ ràng hơn so với việc chuyển đến vị trí bộ nhớ mới. Bạn có thể làm nổi bật con trỏ một lần nữa bằng cách nhấp vào biểu tượng bộ nhớ của con trỏ trong ngăn Phạm vi.

Kết luận

Bài viết này mô tả những điểm cải tiến của chúng tôi đối với Trình kiểm tra bộ nhớ để gỡ lỗi C/C++. Chúng tôi hy vọng các tính năng mới sẽ giúp đơn giản hoá việc gỡ lỗi bộ nhớ của ứng dụng C/C++! Nếu bạn có đề xuất để cải thiện thêm, hãy cho chúng tôi biết bằng cách gửi lỗi!

Bước tiếp theo

Để tìm hiểu thêm, hãy xem: