10

Tôi hiện đang trong quá trình xây dựng một hệ thống nhúng, sử dụng bộ xử lý ARM Cortex M3, với 64 KB SRAM. Hiện tại, tôi đang tìm cách để đảm bảo hiệu suất xác định với các container STL, bao gồm việc đảm bảo rằng tôi không thể hết bộ nhớ trong thời gian chạy.STL trong hệ thống nhúng với bộ nhớ rất hạn chế

Tôi chủ yếu quan tâm đến cách các container STL thực hiện phân bổ bộ nhớ động. Mặc dù tôi có thể sử dụng một phân bổ tùy chỉnh để có các cấu trúc này lấy bộ nhớ từ một nhóm mà tôi đặt sang một bên, tôi sẽ cần phải thiết lập một nhóm riêng biệt cho mỗi cấu trúc để đảm bảo một thể hiện của một cấu trúc không thể chiếm không gian của một cá thể khác.

Tôi đang làm việc với các cá nhân khác trong dự án này, những người không muốn quan tâm đến việc cấp phát bộ nhớ và muốn sử dụng cấu trúc dữ liệu "nổi tiếng" (stack, queue, deque, v.v ...) . Vì vậy, tôi hiện đang xem xét việc xây dựng các trình bao bọc xung quanh C-mảng để cung cấp các cấu trúc này. Điều này sẽ cho phép phân bổ tĩnh bộ nhớ cần thiết để hỗ trợ các thùng chứa này và cho phép các nhà phát triển khác biết kích thước của vùng chứa mà họ đã khởi tạo trước thời gian chạy, dựa trên thông tin kích thước mã do trình biên dịch cung cấp. Theo ý kiến ​​của tôi, điều này đảm bảo rằng các vấn đề cúp bộ nhớ không thể xảy ra trong thời gian chạy, và đơn giản hóa thiết kế hệ thống đáng kể.

Tùy chọn khác sẽ liên quan đến phân bổ container STL khi khởi tạo hệ thống. Sau giai đoạn khởi tạo, không thể phân bổ bộ nhớ động bổ sung. Tuy nhiên, với kiến ​​thức của tôi, các cấu trúc dữ liệu C++ STL chuẩn không hỗ trợ điều này - nó sẽ yêu cầu các thùng chứa như một ngăn xếp có khả năng được phân bổ trước (tương tự như một vectơ).

Tôi đánh giá cao bất kỳ nhận xét nào về đề xuất của tôi về việc xây dựng các lớp học xung quanh tiêu chuẩn C-mảng? Ngoài ra, có cách nào đơn giản hơn để phân bổ một vùng chứa STL kích thước tĩnh, chẳng hạn như một chồng xếp hàng hoặc kích thước tĩnh, tại thời gian biên dịch không? (Tôi biết điều này là có thể với vector, nhưng những người khác tôi không chắc chắn)

Lưu ý: Tôi đã đọc qua một câu hỏi khác (Embedded C++ to use STL or not), nhưng tác giả của câu hỏi này không làm rõ bộ nhớ của họ đã có (khác sau đó làm thế nào họ đã được sử dụng một quá trình ARM7) hoặc xuất hiện để được xem xét một giải pháp tương tự như tôi.

Lưu ý thứ hai: Tôi biết rằng đối với một số nhà phát triển, 64 KB SRAM có thể trông giống như nhiều bộ nhớ. Trong thực tế, tôi đã thực hiện phát triển trên bộ vi xử lý AVR với bộ nhớ ít hơn đáng kể, vì vậy tôi hiểu quan điểm này. Tuy nhiên, từ quan điểm hiện tại của tôi (có lẽ không được hiểu rõ), 64 KB bộ nhớ không nhiều khi nói về các container STL.

+1

Vào cuối ngày, tôi đã đi với EASTL. Dễ sử dụng và hoạt động tốt. – BSchlinker

Trả lời

10

Câu hỏi này là loại bối rối và kỳ lạ. Đầu tiên, hãy làm sáng tỏ một số quan niệm sai lầm.

Bạn đề cập đến "stack, queue, deque" theo tên. Vâng, hai trong số này không phải là vùng chứa. stackqueue là bộ điều hợp vùng chứa. Hãy xem, họ không thực sự lưu trữ trực tiếp các yếu tố; họ chỉ đơn giản là dàn xếp giao diện cho họ. stack đảm bảo rằng bạn chỉ có thể đẩy, bật và lấy phần tử trên cùng. queue đảm bảo rằng bạn chỉ có thể đẩy lùi, bật trước và nhận phần tử phía trước (nghĩ rằng nó cũng cho phép bạn lấy lại phần tử).

Bộ điều hợp vùng chứa thực sự là một trong các tham số mẫu của chúng mà loại vùng chứa thực tế sẽ sử dụng. Vì vậy, bạn có thể sử dụng số stack với số std::list nếu muốn. Tôi không nhất thiết phải đề xuất (tùy thuộc vào trường hợp sử dụng của bạn), nhưng bạn có thể.

Bộ điều hợp vùng chứa không quan tâm đến bộ nhớ; đó là các thùng chứa mà họ sử dụng cấp phát bộ nhớ.

Nếu bạn đang chạy trong một hệ thống hạn chế bộ nhớ chặt chẽ như vậy, bạn sẽ không tìm thấy các thùng chứa tiêu chuẩn để được terribly thân thiện. Thậm chí nếu bạn sử dụng các trình cấp phát để cung cấp cho chúng bộ đệm bộ nhớ có kích thước cố định, điều duy nhất mà những người cấp phát có thể thực hiện để ngăn chặn vùng chứa thực tế phân bổ bộ nhớ nhiều hơn là ném một ngoại lệ.

Ví dụ, nếu bạn có một vector mà cần phải làm việc trong 2KB bộ nhớ, nếu nó có kích thước 1KB, và cố gắng phân bổ 2.5KB hơn, bộ cấp có thể không chỉ đơn giản là trở 2KB. Có thể trả lại 2.5KB theo yêu cầu hoặc némstd::bad_alloc. Đó là hai lựa chọn duy nhất của bạn. Không có cách nào để cấp phát cho biết vector rằng nó có thể nhận được nhiều bộ nhớ hơn so với những gì nó có, nhưng không nhiều như nó muốn.

Tương tự, người cấp phát được yêu cầu cung cấp bộ nhớ mới, bộ nhớ được cấp phát mới có thể được sao chép vào. Nó không phải là nghĩa vụ phải cung cấp cùng một vị trí của bộ nhớ chỉ với nhiều hơn của nó có sẵn. Làm như vậy có thể sẽ gây ra vấn đề trong một số triển khai.

Máy phân phối nhằm cung cấp các vùng bộ nhớ khác nhau để truy cập; chúng không được thiết kế tốt để hạn chế kích thước của thùng chứa.

Đề xuất của tôi là theo dõi a copy of EASTL. Nó thực sự được thiết kế cho loại điều này. Repo Github tôi liên kết với bạn để có một số sửa lỗi và vv, nhưng nó vẫn chủ yếu là như nhau. Nó không phải là một chút mã. Các container giống như STL của họ cung cấp hầu hết giao diện, do đó chúng có thể được thay thế chủ yếu là drop-in. Nhưng chúng cung cấp chức năng đặc biệt để kiểm soát đặc biệt phân bổ bộ nhớ.

+0

Cảm ơn con trỏ tới nguồn EASTL - Tôi không biết nguồn đó đã từng được phát hành chưa. Lần cuối cùng tôi nhìn vào EASTL (một thời gian dài trước đây), có vẻ như chỉ có tài liệu n2271 có sẵn (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2271. html). Hy vọng rằng tôi sẽ có một thời gian để xem xét các nguồn phát hành cho đến nay. –

+0

Đây có lẽ là một ví dụ khác về nơi cplusplus.com đã làm tổn thương tôi, vì tôi đã học cách liên kết "Vùng chứa STL" với ngăn xếp/hàng đợi/v.v. từ họ (http://www.cplusplus.com/reference/stl/). Tôi biết làm thế nào một 'danh sách' có thể được sử dụng như một chồng, vv (Tôi đã thực hiện một khóa học cấu trúc dữ liệu mà tôi đã phải xây dựng các bộ điều hợp container). Tôi đã biết EASTL - mặc dù dường như có một chút tranh cãi liên quan đến nó trong các câu trả lời khác (xem câu trả lời tôi đã liên kết trong câu hỏi ban đầu của tôi). – BSchlinker

+0

stack, queue, dequeue là các cấu trúc dữ liệu theo nghĩa chung, rằng STL đã quyết định thực hiện chúng như các adapter chỉ đơn thuần là một chi tiết thực hiện. Vì vậy, tôi không nghĩ rằng có bất cứ điều gì đặc biệt sai với cách OP xây dựng câu hỏi của mình. Vẫn còn rất vững lời khuyên! – Ylisar

0

Bên cạnh EASTL, bạn cũng có thể sử dụng static_vector từ tăng cường. Nó chia sẻ hầu hết các API với std::vector và nó có thể được sử dụng với bộ điều hợp container (xếp hàng, ngăn xếp). Thay vì ném std::bad_alloc, nó có thể gọi throw_bad_alloc(), vì vậy nó có thể được sử dụng trong môi trường được nhúng mà không có ngoại lệ.