Cách phát hiện rò rỉ bộ nhớ trong C/C++ bằng Valgrind

Cach Phat Hien Ro Ri Bo Nho Trong C C Bang Valgrind



Valgrind là một công cụ được sử dụng rộng rãi để gỡ lỗi và lập hồ sơ các chương trình phần mềm chủ yếu được viết bằng C, C++ và các ngôn ngữ khác. Nó giúp các nhà phát triển phát hiện rò rỉ bộ nhớ, theo dõi các lỗi truy cập bộ nhớ và lập hồ sơ thực thi các chương trình của họ.

Khi bạn chạy một chương trình trong Valgrind, nó sẽ tự động điều chỉnh khả năng thực thi của chương trình, cho phép chương trình giám sát hành vi thực thi và sử dụng bộ nhớ của chương trình.

Rò rỉ bộ nhớ trong C++

Điều quan trọng cần lưu ý là Valgrind được thiết kế chủ yếu cho các chương trình C và C++ và có thể không hoạt động hiệu quả với các ngôn ngữ khác hoặc trong mọi tình huống. Ngoài ra, việc chạy một chương trình trong Valgrind có thể làm chậm đáng kể việc thực thi chương trình, do đó, nó thường được sử dụng trong quá trình phát triển và gỡ lỗi thay vì trong môi trường sản xuất.







Khi bộ nhớ được tạo động không được giải phóng đúng cách, nó có thể gây rò rỉ bộ nhớ trong C/C++, điều này sẽ làm cạn kiệt dần tài nguyên bộ nhớ sẵn có. Điều này có thể dẫn đến việc tiêu thụ quá nhiều bộ nhớ và làm giảm hiệu suất của chương trình.



Cài đặt Valgrid

Để cài đặt Valgrind trên hệ thống Linux, hãy mở một thiết bị đầu cuối và cập nhật kho lưu trữ gói của bạn bằng trình quản lý gói dành riêng cho bản phân phối Linux của bạn. Lệnh sau hoạt động với các hệ thống dựa trên Ubuntu và Debian:



$ sudo cập nhật thích hợp

Sử dụng trình quản lý gói để cài đặt Valgrind. Một lần nữa, lệnh có thể khác nhau tùy thuộc vào bản phân phối Linux của bạn. Sử dụng lệnh sau cho các hệ thống dựa trên Ubuntu và Debian:





$ sudo đúng cách cài đặt cổng bầu cử

Khi được nhắc, hãy nhập mật khẩu người dùng của bạn và nhấn “Enter”. Lưu ý rằng tài khoản người dùng của bạn cần có quyền quản trị để cài đặt phần mềm. Trình quản lý gói tải xuống và cài đặt Valgrind cùng với mọi phụ thuộc cần thiết. Quá trình này có thể mất một vài phút.



Sau khi quá trình cài đặt kết thúc, bạn có thể xác nhận cài đặt Valgrind thành công bằng cách thực hiện lệnh sau như một bước xác minh:

$ cổng bầu cử --phiên bản

Lệnh này hiển thị thông tin phiên bản của Valgrind nếu nó được cài đặt thành công.

Đó là nó! Valgrind hiện đã được cài đặt trên hệ thống Linux của bạn và bạn có thể sử dụng nó để phân tích và gỡ lỗi các chương trình C/C++ của mình để phát hiện rò rỉ bộ nhớ và các vấn đề khác.

Tạo một tập tin trong Ubuntu

Để bắt đầu làm việc với chương trình, trước tiên chúng ta cần tạo một tệp trong Ubuntu. Để tạo tập tin, chúng tôi sử dụng trình soạn thảo văn bản nano. Vì vậy, chúng ta viết lệnh trên terminal như sau:

$ nano tập tin1

Ở đây nano là tên của trình soạn thảo văn bản đang được thực thi. Đối số “file1” đại diện cho tên của tệp mà bạn định mở hoặc tạo bằng trình soạn thảo văn bản nano. Nano mở tệp để chỉnh sửa nếu nó đã tồn tại; nếu không, nó sẽ tạo một tệp mới với tên được cung cấp. Vì chúng tôi không có tệp như vậy nên nó sẽ tạo một tài liệu mới có tên “file1”.

Sau khi bạn chạy lệnh, trình chỉnh sửa nano sẽ mở ra, cung cấp cho bạn một khung vẽ trống để nhập hoặc chỉnh sửa nội dung của tệp “file1”. Bạn có thể bắt đầu nhập hoặc dán nội dung hiện có vào trình chỉnh sửa.

Bây giờ đã đạt được tất cả các điều kiện tiên quyết, chúng tôi tạo một số ví dụ để sử dụng Valgrind nhằm phát hiện rò rỉ bộ nhớ trong các chương trình C++.

Ví dụ 1:

Ví dụ đầu tiên mà chúng tôi cung cấp minh họa một ví dụ đơn giản về cấp phát bộ nhớ động bằng cách sử dụng hàm “malloc” từ thư viện trong C.

#include

int chủ yếu ( )

{

ký tự * Một = malloc ( 102 ) ;

trở lại 0 ;

}

Đây là bản phân tích mã:

Trước tiên, chúng tôi bao gồm tệp tiêu đề thư viện chuẩn cung cấp các chức năng như malloc để phân bổ và giải phóng bộ nhớ động.

Dòng int main() khai báo hàm main. Sau đó, char *a = malloc(102); khai báo một biến con trỏ “a” kiểu char* (con trỏ tới char). Nó sử dụng hàm “malloc” để phân bổ động bộ nhớ cho một mảng gồm 102 phần tử char (tổng cộng 102 byte). Kích thước cấp phát bộ nhớ, được biểu thị bằng byte, được gửi dưới dạng đầu vào cho hàm malloc và nó xuất ra một con trỏ tới khối bộ nhớ mới được tạo. Con trỏ char* “a” được gán giá trị con trỏ này. Cuối cùng là “return 0;” báo hiệu sự kết thúc của chức năng chính.

Nói tóm lại, mã này phân bổ động bộ nhớ cho một mảng gồm 102 phần tử char sử dụng “malloc” và gán địa chỉ bộ nhớ cho con trỏ “a”. Tuy nhiên, lưu ý rằng mã không sử dụng hoặc thao tác bộ nhớ được phân bổ theo bất kỳ cách nào và không bao gồm việc giải phóng bộ nhớ bằng cách sử dụng miễn phí.

Khi chúng tôi chạy chương trình này thông qua Valgrind với tùy chọn “–leak-check=full”, nó sẽ thực hiện kiểm tra rò rỉ bộ nhớ và cung cấp báo cáo đầu ra.

Báo cáo đầu ra do Valgrid tạo ra được đưa ra như sau:

Ví dụ 2:

Để bắt đầu với hình minh họa này, trước tiên chúng tôi tạo tệp “test2” bằng trình soạn thảo văn bản nano như đã giải thích trước đó bằng cách viết lệnh:

$ nano thử nghiệm2

Bây giờ, chúng tôi viết chương trình C++ để kiểm tra xem có rò rỉ bộ nhớ nào không bằng Valgrind:

#include

#include

#include

const int a_s = 3000 ;

int chính ( ) {

int * ia = malloc ( kích thước của ( int ) * BẰNG ) ;

( int tôi = 0 ; Tôi < BẰNG; tôi++ ) {

[ Tôi ] = tôi;

}

mảnh vụn ( thời gian ( VÔ GIÁ TRỊ ) ) ;

int rn = rand ( ) % BẰNG;

printf ( 'nó[%d]: %d \N ' , ừ, nó [ rn ] ) ;

trở lại 0 ;

}

Hãy cùng tìm hiểu chương trình.

Mã này bao gồm các tệp tiêu đề cần thiết và xác định biến không đổi “a_s” có giá trị 3000. Bên trong hàm main(), một con trỏ “ia” kiểu int* được khai báo và bộ nhớ được cấp phát động bằng cách sử dụng “malloc” chức năng. Biểu thức “sizeof(int) * a_s” xác định tổng bộ nhớ cần thiết để lưu trữ số nguyên “a_s”. Tất cả các phần tử của mảng “ia” được khởi tạo bởi vòng lặp “for” với giá trị chỉ mục tương ứng. Ví dụ: ia[0] sẽ là 0, ia[1] sẽ là 1, v.v.

Trình tạo số ngẫu nhiên được tạo bằng cách sử dụng hàm “srand” theo thời gian hiện tại. Điều này đảm bảo rằng chương trình tạo ra một tập hợp các số nguyên ngẫu nhiên duy nhất mỗi lần nó được thực thi. Hàm “rand” tạo ra một số ngẫu nhiên và “rn” được gán với kết quả là rand() % a_s. Toán tử mô đun “%” giới hạn phạm vi của số ngẫu nhiên nằm trong khoảng từ 0 đến a_s – 1 tương ứng với một chỉ mục hợp lệ trong mảng “ia”.

Cuối cùng, chương trình sử dụng hàm “printf” để in giá trị tại chỉ mục “rn” được chọn ngẫu nhiên của mảng “ia”, cùng với chỉ mục tương ứng.

Khi bạn chạy chương trình này thông qua Valgrind, nó sẽ tạo ra báo cáo đầu ra sau:

  Ảnh chụp màn hình chương trình máy tính Mô tả được tạo tự động

Phần kết luận

Chúng tôi đã phát hiện ra cách sử dụng công cụ Valgrind để phát hiện rò rỉ bộ nhớ trong chương trình C++. Hướng dẫn cài đặt Valgrind được cung cấp ban đầu. Sau đó, chúng tôi đã giải thích chi tiết về cách tạo tệp trong Ubuntu bằng trình soạn thảo văn bản nano. Cuối cùng, bằng cách sử dụng các điều kiện tiên quyết này, chúng tôi đã thực thi hai ví dụ C++ để kiểm tra rò rỉ bộ nhớ trong đó. Báo cáo do Valgrind tạo cũng được đính kèm cho thấy rò rỉ bộ nhớ trong tệp được cung cấp.