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 Memory Inspector (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 Công cụ kiểm tra để gỡ lỗi C/C++ cũng như những thách thức kỹ thuật gặp phải trong quá trình gỡ lỗi.

Dưới đây là một số bài đăng trên blog có liên quan nếu bạn chưa quen với việc 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 byte của đối tượng trong số các bộ nhớ WebAssembly xung quanh là một vấn đề. Bạn cần biết kích thước của đối tượng và số byte từ đầu. 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 thể hiện rõ byte nào khác thuộc về mảng đó. Sẽ rất tuyệt nếu bạn có thể nhận ra ngay lập tức tất cả các byte thuộc đối tượng phải không?

Ảnh chụp màn hình 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++. Thao tác này sẽ giúp bạn phân biệt chúng với kỷ niệm 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ỡ

Hãy xem video dưới đây để thấy cách hoạt động của Trình kiểm tra bộ nhớ. Khi bạn hiển thị 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 khối mới ngay phía trên nó. Khối này nhắc bạn tên và loại kỷ niệm đượ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 đó để bỏ đá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ẽ 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 vào byte hoặc khối bất kỳ của đối tượng một lần nữa.

Khả 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ác 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ớ ứng dụng C/C++ của bạn dễ dàng hơn bao giờ hết!

Bạn muốn dùng thử? 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. Settings > Experimental > WebAssemble Debugging: 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 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 dưới đây, 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 đã nhầm lẫn khi tính toán con trỏ và giờ đây thay vì in phần tử cuối cùng, chương trình này 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 sẽ chuyển sang Trình kiểm tra bộ nhớ để gỡ lỗi sự cố. 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 đú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, chúng cho 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! Nhờ trang bị kiến thức này, lập trình viên nhận ra rằng họ đã đếm sai độ lệch 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 được con trỏ &quot;lastNumber&quot; trỏ đến. Bộ nhớ được làm nổi bật 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 tính năng 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ớ, nhờ đó có thể 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 tìm ra nội dung cần làm nổi bật

Trong phần này, chúng ta sẽ tìm hiểu hệ sinh thái gồm 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 thực hiện 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 có 2 điều sau:

  • Tiện ích DWARF C/C++ được cài đặt trong Chrome
  • Các 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 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ờ có 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 trong C hoặc C++ dưới dạng WebAssembly và thực thi chú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 tìm ra biến WebAssembly tương ứng với biến C/C++, v.v. Bằng cách này, Công cụ cho nhà phát triển có thể hiển thị cho bạn 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 biết, 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ì sẽ thực 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 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 bộ nhớ liên quan và biết được loại bộ nhớ, đồng thời cũng 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ể 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, kết quả là gì? Trình kiểm tra sử dụng 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 thấy nội dung mà con trỏ trỏ đến.

Duy trì điểm nổi bật ở các bước 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ẽ giữ nguyên nội dung đánh dấu nếu cho rằ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 phát triển 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 điểm ngắt mới, Memory Inspector (Trình kiểm tra bộ nhớ) một lần nữa sẽ truy vấn V8 và phần mở rộng cho biến được liên kết với điểm đánh dấu trước đó. Sau đó, Google Analytics 4 sẽ so sánh vị trí và loại của các đối tượng. Nếu các chi tiết khớp nhau, thì điểm nổi bật sẽ vẫn tồn tại. Trong video ở trên, có một vòng lặp được 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 nên 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 đến con trỏ như thế nào. Nếu bạn có con trỏ được đánh dấu và chỉ định lại con trỏ đó cho một đối tượng khác, 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ỳ đâ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á phần đánh dấu sẽ rõ ràng hơn so với việc chuyển sang một vị trí bộ nhớ mới. Bạn có thể đánh dấu lại con trỏ 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ớ cho ứng dụng C/C++ của bạn! Nếu bạn có đề xuất để cải thiện hơn nữa, 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: