Lỗi kép miễn phí hoặc lỗi tham nhũng trong C ++

Bài viết đăng tại: https://programming.laptrinh.site

Hướng dẫn này sẽ thảo luận về các vấn đề xảy ra trong cấp phát bộ nhớ động trong C++. Khi sử dụng bộ nhớ heap, chúng tôi gặp phải nhiều vấn đề rất quan trọng cần được giải quyết trong khi thực hiện quản lý bộ nhớ heap.

Đầu tiên, chúng ta sẽ thảo luận về cách chúng ta cấp phát bộ nhớ và các phương thức khác nhau được cung cấp trong C++; sau đó, chúng tôi sẽ chuyển sang các nguyên nhân và giải pháp của lỗi double free or corruption trong C++.

Cấp phát và giải phóng bộ nhớ động trong C++

C++ cho phép chúng ta phân bổ bộ nhớ biến hoặc mảng trong thời gian chạy. Điều này được gọi là cấp phát bộ nhớ động.

Trong các ngôn ngữ lập trình khác, chẳng hạn như Java và Python, trình biên dịch tự động duy trì bộ nhớ biến. Tuy nhiên, đây không phải là trường hợp trong C++.

Trong C++, chúng ta phải giải phóng bộ nhớ được cấp phát động theo cách thủ công sau khi chúng ta không còn cần nó nữa. Chúng tôi có thể phân bổ và giải phóng bộ nhớ một cách linh hoạt bằng cách sử dụng các chức năng newdelete .

Có hai chức năng khác, tức là mallocfree , cũng được bao gồm trong C++ để cấp phát và hủy cấp phát bộ nhớ động.

Hãy xem xét một ví dụ dưới đây minh họa việc sử dụng các chức năng newdelete .

#include <iostream>
using namespace std;

int main() {
  int* ptr;
  ptr = new int;
  *ptr = 40;
  cout << *ptr;
  delete ptr;
  return 0;
}

Chúng tôi đã cấp phát bộ nhớ động cho một biến int bằng cách sử dụng toán tử ‘mới’. Cần lưu ý rằng chúng tôi đã sử dụng biến tham chiếu ptr để cấp phát bộ nhớ động.

Toán tử new trả về địa chỉ của vị trí bộ nhớ. Trong trường hợp của một mảng, toán tử new trả về địa chỉ của phần tử đầu tiên của mảng.

Chúng ta có thể giải phóng bộ nhớ được sử dụng bởi một biến được khai báo động sau khi chúng ta không cần sử dụng nó nữa. Toán tử delete được sử dụng cho việc này.

Nó trả lại bộ nhớ cho hệ điều hành. Điều này được gọi là giải phóng bộ nhớ.

Ví dụ tiếp theo sẽ cho bạn thấy minh họa về các mallocfree .

#include <iostream>
#include <cstdlib>
using namespace std;

int main() {

int* ptr2 = (int*) malloc(sizeof(int));
*ptr2 = 50;

cout << *ptr2;
free(ptr2);
return 0;
}

Trong C++, phương thức malloc() gán một con trỏ tới một khối bộ nhớ chưa được khởi tạo. Tệp tiêu đề cstdlib xác định nó.

malloc lấy tham số là kích thước của bộ nhớ bạn cần cấp phát và trả về một con trỏ trống trỏ đến khối bộ nhớ đã cấp phát. Do đó nó có thể được đánh máy theo yêu cầu của chúng tôi.

Mặt khác, phương thức free() giải phóng bộ nhớ được cấp phát bằng cách sử dụng malloc . Nó trả lại bộ nhớ đó cho hệ điều hành và tránh các sự cố rò rỉ bộ nhớ.

Lỗi double free or corruption trong C ++

Lỗi double-free xảy ra khi free() được sử dụng nhiều lần với cùng một địa chỉ bộ nhớ làm đầu vào.

Gọi free() trên cùng một biến hai lần có thể dẫn đến rò rỉ bộ nhớ. Khi một phần mềm chạy free() hai lần với cùng một tham số, cấu trúc dữ liệu quản lý bộ nhớ trong ứng dụng sẽ bị hỏng, cho phép người dùng độc hại ghi giá trị vào bất kỳ vùng bộ nhớ nào.

Lỗi này có thể khiến chương trình bị sập hoặc thay đổi luồng thực thi trong một số trường hợp. Kẻ tấn công có thể đánh lừa chương trình để thực thi mã do chúng lựa chọn bằng cách ghi đè lên các thanh ghi hoặc vùng bộ nhớ cụ thể, dẫn đến hệ vỏ tương tác có quyền cao hơn.

Một danh sách liên kết của bộ đệm trống được đọc khi bộ đệm trống free() ‘d sắp xếp lại và kết hợp các phần của bộ nhớ trống (để phân bổ bộ đệm lớn hơn trong tương lai). Các khối này được tổ chức trong một danh sách liên kết đôi với các liên kết đến các khối trước và sau chúng.

Kẻ tấn công có thể ghi các giá trị tùy ý vào bộ nhớ bằng cách hủy liên kết bộ đệm không sử dụng (xảy ra khi gọi free() ), ghi đè hiệu quả các thanh ghi có giá trị và khởi chạy shellcode từ bộ đệm của nó.

Hãy xem xét một ví dụ dưới đây.

#include <iostream>
#include <cstdlib>
using namespace std;

int main() {

  int* ptr2 = (int*) malloc(sizeof(int));
  *ptr2 = 50;

  cout << *ptr2;
  free(ptr2);
  free(ptr2);
  return 0;
}

Đầu ra:

 free(): double free detected in cache 2 Aborted

Trong đoạn mã trên, chúng tôi đã sử dụng hàm free() hai lần, điều đó có nghĩa là chúng tôi đang cố gắng giải phóng bộ nhớ đã trống và không được cấp phát nữa. Điều này tạo ra sự cố rò rỉ bộ nhớ và là nguyên nhân gốc rễ khiến mã bị lỗi.

Có nhiều tình huống khác cũng có thể gặp phải lỗi như vậy. Nhưng có ba lý do phổ biến (và thường trùng lặp) đối với các lỗ hổng không có kép.

  1. Điều kiện lỗi và các tình huống bất thường khác
  2. Sau khi không gian bộ nhớ đã được giải phóng, nó sẽ được sử dụng.
  3. Nhầm lẫn về phần nào của chương trình chịu trách nhiệm giải phóng bộ nhớ

Mặc dù một số lỗ hổng double-free không phức tạp hơn nhiều so với ví dụ trước, nhưng hầu hết chúng được phân phối trên hàng trăm dòng mã hoặc thậm chí nhiều tệp. Các lập trình viên dường như đặc biệt có xu hướng giải phóng các biến toàn cục nhiều lần.

Cách tránh lỗi double free or corruption lỗi trong C ++

Loại lỗ hổng này có thể tránh được bằng cách gán NULL cho con trỏ của chúng ta bất cứ khi nào nó rảnh (nghĩa là bộ nhớ được trỏ bởi con trỏ này sẽ trống). Theo đó, hầu hết các trình quản lý heap đều bỏ qua các con trỏ null miễn phí.

Bạn nên null tất cả các con trỏ đã xóa và kiểm tra xem tham chiếu có null hay không trước khi giải phóng nó. Khi bắt đầu mã của chúng tôi, chúng tôi phải khởi tạo con trỏ null trước khi sử dụng con trỏ đó trong mọi trường hợp.

URL Link

https://laptrinh.site/loi-kep-mien-phi-hoac-loi-tham-nhung-trong-c/

Viết bởi Duy Mạnh. Đã đăng ký bản quyền tác giả tại Creativecommons và DMCA