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 nhiều 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 byte của đối tượng trong số bộ nhớ WebAssembly xung quanh là một điểm bất tiệ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 dưới đây, byte đầu tiên của mảng int32 gồm 10 phần tử được chọn nhưng chưa rõ byte nào khác thuộc mảng đó. Chẳng phải thật tuyệt nếu bạn có thể nhận ra ngay tất cả các byte thuộc đố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++. Nhờ vậy, bạn có thể phân biệt chúng 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ỡ

Xem video dưới đây để xem Trình kiểm tra bộ nhớ hoạt động như thế nào. Khi bạn tiết lộ mảng x trong Trình kiểm tra bộ nhớ, bộ nhớ được đánh dấu sẽ xuất hiện trong Trình xem bộ nhớ cùng với một chip mới ngay phía trên. Khối này sẽ nhắc bạn tên và loại của bộ nhớ được đánh dấu. Nhấp vào khối để 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 đánh dấu.

Khi bạn chọn một byte bên ngoài đối tượng bạn kiểm tra, phần đánh dấu sẽ làm mờ nét để 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 ở 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. Cài đặt > Thử nghiệm > Gỡ lỗi WebAssemble: Bật 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, một lập trình viên sẽ tạo một mảng số nguyên và quyết định sử dụng số học 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ể theo dõi bản minh hoạ này! Trước tiên, họ sẽ kiểm tra mảng trong Memory Inspector (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 đúng như dự kiến.

Ảnh chụp màn hình trình kiểm tra bộ nhớ đã mở với một mảng int32 đã được kiểm tra. Tất cả cá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 trong 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 trình kiểm tra bộ nhớ đã mở cho thấy bộ nhớ được làm nổi bật do 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 ví dụ này minh hoạ cách tính năng 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ớ. Điều này có thể giúp bạn hiểu rõ hơn những gì đang xảy 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ác công cụ cho phép 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:

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

Nhưng tại sao? V8 (công cụ WebAssembly và JavaScript 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 xây dựng trong 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 muốn tìm hiểu thêm, hãy tham khảo bài đăng này trên blog để tham khảo ví dụ về dữ liệu gỡ lỗi DWARF.

Vậy điều gì thực sự sẽ xảy ra khi bạn tiết lộ 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à tiện ích cho biến đã liên kết với điểm đá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 hai giá trị khớp nhau, điểm nổi bật sẽ giữ nguyê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ó con trỏ đã đánh dấu rồi gán lại cho một đối tượng khác, thì vị trí cũ và vị trí mới của đối tượng được đánh dấu sẽ khác nhau và điểm đánh dấu 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: