2009-04-21 31 views
6

Bất kỳ đề xuất nào cho bộ cấp phát dựa trên stack của tôi? (Trừ gợi ý để sử dụng một lớp với các thành viên private/public)Cải tiến cho bộ cấp phát ngăn xếp C++ này?

struct Heap 
{ 
    void* heap_start; 
    void* heap_end; 
    size_t max_end; 

    Heap(size_t size) 
    { 
     heap_start = malloc(size); 
     heap_end = heap_start; 
     max_end = size + (size_t) heap_start; 
    } 

    ~Heap() 
    { 
     ::free(heap_start); 
    } 

    void* allocate(size_t bytes) 
    { 

     size_t new_end = ((size_t) heap_end) + bytes; 

     if(new_end > max_end) 
      throw std::bad_alloc(); 

     void* output = heap_end; 
     heap_end = (void*) new_end; 
     return output; 
    } 

} 
+0

Bộ nhớ C++ của tôi như thế nào? – paxdiablo

+0

Chỉ cần tự hỏi nếu có bất kỳ cách nào để tối ưu hóa nó, hoặc các quy ước tốt hơn, vv .. – Unknown

+0

Được rồi, sửa tiêu đề để làm cho nó rõ ràng hơn. – paxdiablo

Trả lời

4

Bạn đã triển khai bộ phân bổ dựa trên stack. Bạn không thể giải phóng mà không để lại khoảng trống. Thông thường một hồ bơi đề cập đến một khối bộ nhớ tiếp giáp với các khe có kích thước cố định, được liên kết gấp đôi để cho phép liên tục thêm thời gian và xóa.

Here's one bạn có thể sử dụng làm hướng dẫn. Nó nằm dọc theo các dòng giống như của bạn nhưng bao gồm các trình lặp cơ bản trên các nút được cấp phát và sử dụng các mẫu để nhận biết kiểu.

+0

À vâng, có vẻ như là từ đúng. Tôi nghĩ rằng nó được gọi là một hồ bơi bộ nhớ. – Unknown

2

Hai vấn đề rõ ràng:

1/Bạn không có deallocate().

2/A deallocate() sẽ rất khó viết với chiến lược hiện tại của bạn trừ khi bạn luôn định xử lý theo thứ tự đảo ngược chính xác của phân bổ. Bạn sẽ cần phải phục vụ cho trường hợp một khách hàng muốn deallocate bộ nhớ ở giữa phần được sử dụng của bạn.

Tất nhiên, nếu bạn giao dịch theo thứ tự ngược lại, (2) không phải là vấn đề. Và nếu bạn không bao giờ giải phóng bộ nhớ, (1) cũng không phải là vấn đề.

Tùy thuộc vào những gì bạn muốn.

+0

Cũng như một nhóm bộ nhớ thông thường, bạn chỉ cần phân bổ một loạt các đối tượng, và sau đó deallocate tất cả trong 1 cuộc gọi chức năng. Nhưng sau đó tôi hoàn toàn quên mất điểm yếu của sharptooth mà tôi có thể cần phải gọi mỗi người hủy diệt của họ nếu họ không phải là POD. – Unknown

+0

Bạn chỉ cần gọi các destructors nếu họ có tập tin xử lý/các đối tượng khác mở mà không sống trong hồ bơi. Nếu tất cả mọi thứ chỉ phân bổ bộ nhớ và tất cả bộ nhớ đó nằm trong nhóm, bạn không cần phải gọi destructors. –

1

Heap của bạn không cho phép deallocation. Bạn sẽ sử dụng nó như thế nào cho các đối tượng được phân bổ với mới trong C++?

+0

Bạn đưa ra một điểm tốt Tôi cho rằng, tôi chỉ nghĩ đến việc chứa POD. – Unknown

+0

Ngay cả với POD, bạn sẽ phải xử lý thao tác xóa.Nếu bạn không làm như vậy, toán tử xóa mặc định sẽ được sử dụng, điều này có thể sẽ làm hỏng chương trình của bạn. – sharptooth

+0

Bạn đề xuất điều gì? Tôi có cần ghi đè toán tử xóa toàn cầu không? – Unknown

4
size_t new_end = ((size_t) heap_end) + bytes; 

Không tốt, không bao giờ làm những việc như thế, bạn cho rằng sizeof (size_t) == sizeof (void *), còn những gì sẽ xảy ra nếu bytes==(size_t)(-1) này sẽ không hoạt động

Thêm vào đó, bạn cần đảm bảo rằng con trỏ mà bạn đang trả về được căn chỉnh. Nếu không bạn sẽ gặp vấn đề. Vì vậy, bạn cần đảm bảo rằng các byte là bội số của 4 hoặc 8 theo nền tảng của bạn.

class {... 
char *max_end,*head_end,*heap_start; 
}; 

... 
max_end=heap_start+size; 
... 
bytes=align_to_platform_specific_value(bytes); 
if(max_end-heap_end >= bytes) { 
    void* output = (void*)heap_end; 
    heap_end+=bytes; 
    return output; 
} 
throw std::bad_alloc(); 

Đề xuất? Đừng sáng tạo lại bánh xe. Có rất nhiều thư viện hồ bơi tốt.

+0

Nhưng lý do tôi không sử dụng char là vì char không được bảo đảm là 1 byte. size_t với kiến ​​thức của tôi luôn luôn là void * vì một loại có thể kéo dài toàn bộ không gian địa chỉ. Ngoài ra trình biên dịch gcc của tôi không cho phép tôi làm void * số học. Nhưng bạn có một điểm với sự liên kết: một sự cân bằng không gian/thời gian của nó. – Unknown

+1

Tiêu chuẩn defiantly xác định sizeof (char) = 1, tiêu chuẩn không xác định sizeof (size_t) == sizeof (void *) thậm chí nó là phổ biến trong thực tế, nhưng nó xác định sizeof (intptr_t) == sizeof (void *) (nhưng intptr_t không phải là avalible cho một số trình biên dịch như VC + +). – Artyom

+0

"sự cân bằng không gian/thời gian của nó". đó là câu hỏi đúng đắn. Trên một số nền tảng (như ARM), một quá trình có thể thất bại nếu bạn truy cập chưa được ký. Ngoài ra, dữ liệu của bạn sử dụng các hoạt động nguyên tử (ví dụ như mutex) nó sẽ thất bại nếu nó không phải là chưa được ký. – Artyom

Các vấn đề liên quan