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

Trong Chrome 92, chúng tôi đã giới thiệu 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 chúng tôi cải thiện Trình kiểm tra cho việc 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à số byte tính từ lúc bắ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 trình kiểm tra bộ nhớ gốc có 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 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 chữ thập sẽ xuất hiện – hãy nhấp vào khối đó để 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 đối tượng, hãy nhấp vào khối hoặc byte bất kỳ của đối tượng một lần nữa.

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 việc khám phá bộ nhớ của các ứng dụng C/C++ trở nên dễ dàng hơn bao giờ hết!

Bạn có muốn dùng thử dịch vụ này không? Bạn sẽ phải:

  • 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 cùng tìm hiểu 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. Thật không may, lập trình viên đã mắc lỗi khi tính toán con trỏ và giờ đây thay vì in phần tử cuối cùng, chương trình lại 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 đến Công cụ kiểm tra bộ nhớ để gỡ lỗi sự cố. 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ẽ thấy biến lastNumber trong ngăn Scope (Phạm vi) và nhận thấy 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 giá trị bù trừ của con trỏ ở dòng 8. Đáng lẽ 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 chỉ ra những điểm cần nhấn mạnh

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 Công cụ cho nhà phát triển, V8, Tiện ích DWARF C/C++ và Emscripten có thể gỡ lỗi C/C++ trong Chrome.

Để khai thác toàn bộ sức mạnh của tính năng gỡ lỗi C/C++ trong Công cụ cho nhà phát triển, bạn cần hai thứ:

  • Đã 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. Nhìn chung, dữ liệu này giúp tiện ích xác định những biến WebAssembly tương ứng với các biến C/C++ của bạn, v.v. Bằng cách này, Công cụ cho nhà phát triển có thể cho bạn thấy các biến C++ của bạn 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ớ, Công cụ cho nhà phát triển sẽ kiểm tra xem bạn muốn kiểm tra biến nào. Sau đó, phương thức này sẽ truy vấn tiện ích về loại dữ liệu và vị trí của lastNumber. Ngay sau khi tiện ích phản hồi thông tin đó, Trình kiểm tra bộ nhớ có thể cho thấy lát bộ nhớ liên quan và biết được loại bộ nhớ, đồng thời có thể 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 chúng ta đã kiểm tra lastNumber: int *, nhưng chip trong Trình kiểm tra bộ nhớ cho biết *lastNumber: int, điều gì mang lại? Trình kiểm tra sử dụng quy trình loại bỏ tham chiếu con trỏ kiểu C++ để cho biết loại đối tượng mà bạn thấy! Nếu bạn kiểm tra một con trỏ, công cụ kiểm tra sẽ cho bạn biết con trỏ trỏ đến vị trí nào.

Duy trì khung hiển thị nổi bật theo các bước của trình gỡ lỗi

Khi bạn hiển thị một đối tượng trong Memory Inspector (Trình kiểm tra bộ nhớ) và thao tác với trình gỡ lỗi, Trình kiểm tra này sẽ duy trì khung làm nổi bật nếu cho rằng đối tượng đó vẫn có thể áp dụng được. Ban đầu, chúng tôi không có tính năng này trong lộ trình gỡ lỗi, nhưng chúng tôi nhanh chóng nhận ra rằng tính năng 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 dưới đây!

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 đó, Analytics sẽ so sánh vị trí và kiểu của các đối tượng. Nếu hai giá trị khớp nhau, điểm nổi bật sẽ vẫn giữ nguyên. Trong video trên, có một vòng lặp cho mảng x. Những thao tác này không làm thay đổi loại hoặc vị trí của mảng, nên mảng được đánh dấu.

Bạn có thể thắc mắc việc 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. Do đối tượng mới được trỏ đến có thể sống ở bất cứ đâu trong Bộ nhớ WebAssembly và có thể sẽ ít liên quan đến vị trí bộ nhớ trước đó, nên việc xoá khung đánh dấu sẽ rõ ràng hơn việc chuyển sang một 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 Scope (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ẽ đơ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 tính năng này hơn nữa, hãy cho chúng tôi biết bằng cách báo cáo lỗi!

Bước tiếp theo

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