2011-11-23 28 views
18

Tôi có nguồn cho thư viện lớn (> 250 tệp) sử dụng nhiều các vùng chứa và chuỗi STL. Tôi cần phải chạy nó trong một môi trường nhúng với heap hạn chế, vì vậy tôi muốn đảm bảo rằng chính thư viện này bị giới hạn trong việc sử dụng đống của nó.Thay thế phân bổ STL mặc định

Giải pháp hiển nhiên là tạo bộ cấp phát, nhưng sửa đổi toàn bộ cơ sở mã để bao gồm thông số mẫu cấp phát là một công việc lớn của phương sách cuối cùng và không mong muốn trong trường hợp tôi muốn dùng phiên bản mới của nguồn. Thay thế toàn cầu mới và xóa là không khả thi vì điều đó ảnh hưởng đến toàn bộ hình ảnh, không chỉ thư viện này.

Suy nghĩ tiếp theo của tôi là một thủ thuật macro C ngu ngốc, nhưng điều đó dường như không thể, mặc dù tôi thừa nhận không phải là tác giả vĩ mô thông minh.

Vì vậy, tôi nghĩ "là có một trình biên dịch hoặc chuyển đổi pragma để xác định phân bổ <> lớp học tại thời gian biên dịch"? Nhưng tôi mở cho bất cứ điều gì.

Câu hỏi tiếp theo tôi sẽ hỏi, nếu có ai có thể đưa ra giải pháp, là cách thực hiện tương tự cho mới/xóa trong tập hợp các tệp bao gồm thư viện này.

Tôi đang sử dụng gcc 3.4.4 toolchain để chạy dưới Cygwin, với mục tiêu của VxWorks, nếu điều đó kích thích bất kỳ ý tưởng nào.

+0

gcc 3.4.4 Đủ tuổi để được gắn nhãn 'hoàn toàn bị hỏng'. Bất kỳ lý do nào khiến bạn không chuyển sang phiên bản mới hơn? – sehe

+0

Tôi nghĩ rằng trong GCC đó chỉ là một macro đơn giản ở đâu đó trong interna, mà bạn sẽ có thể chuyển đổi. Mặc định là "cấp phát mới", nhưng GCC đi kèm với một số lựa chọn thay thế, như "cấp phát malloc" và cấp phát hồ bơi và không có gì. –

+0

Giả sử bạn có thể tạo một heap giới hạn và sau đó quá tải 'toán tử new' cho thư viện này, vì vậy tất cả các cuộc gọi' operator new' trong thư viện đã đi tới vùng hạn chế của bạn. Bạn muốn hành vi nào khi heap giới hạn đầy và quá trình 'toán tử new' được nạp chồng được gọi là? Bạn có thực sự muốn 'toán tử new' thất bại trong những trường hợp đó không? Tôi không tin bạn sẽ làm thế, trừ khi thư viện đó vẫn có thể hoạt động khi 'toán tử new' thất bại. Có lẽ nếu thư viện là một bộ nhớ cache cơ sở dữ liệu, hoặc một cái gì đó như thế. Thư viện làm gì? –

Trả lời

6

tôi dùng đến tiền xử lý để có được một giải pháp khả thi, mặc dù nó hiện dựa vào việc thực hiện GCC 3.4.4 để làm việc.

Triển khai GCC <memory> bao gồm tệp <bits/allocator.h>, bao gồm tệp khác <bits/c++allocator.h>, xác định macro xác định lớp triển khai lớp cơ sở phân bổ mặc định.

Kể từ khi được tìm thấy trong một con đường nền tảng phụ thuộc vào (/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/i686-pc-cygwin/bits), tôi không cảm thấy (rất) bẩn trong thay thế cho nó với riêng thực hiện "nền tảng phụ thuộc vào" của tôi.

Vì vậy, tôi chỉ cần tạo một thư mục bits/ trong thư mục gốc của nguồn của tôi bao gồm đường dẫn, và sau đó tạo tệp c++allocator.h trong thư mục đó. Tôi xác định macro được yêu cầu là tên của lớp cấp phát của tôi và nó hoạt động như một nét duyên dáng, vì gcc tìm kiếm các đường dẫn bao gồm của tôi trước khi tìm kiếm hệ thống bao gồm.

Cảm ơn tất cả các câu trả lời của bạn. Tôi nghĩ rằng tôi có thể đi với "giải pháp" này, mà sẽ chỉ làm việc miễn là tôi đang sử dụng 3.4.4 có lẽ.

+0

bất kỳ suy nghĩ về cách tôi làm điều này trong Visual Studio? Tôi đã cố gắng để xác định vị trí tập tin tiêu đề phân bổ mặc định, nhưng đã bị mất :) cảm ơn! – OSH

3

Vì vậy, tôi nghĩ "có trình biên dịch hoặc chuyển đổi pragma để chỉ định phân bổ <> lúc biên dịch" không? Nhưng tôi mở cho bất cứ điều gì.

Không có.

Hãy xem here.

Allocators là đối số mẫu trong mỗi vùng chứa stl. Bạn sẽ cần phải thay đổi chúng. Tôi đã làm điều tương tự trong quá khứ, khi làm việc trên nhúng. Tôi có thể cung cấp cho bạn một số gợi ý nếu bạn thích:

Basic mẫu cấp phát:

namespace PFM_MEM { 
    template <class T> 
    class CTestInstAllocator { 
    public: 
     // type definitions 
     typedef size_t size_type; 
     typedef ptrdiff_t difference_type; 
     typedef T*  pointer; 
     typedef const T* const_pointer; 
     typedef T&  reference; 
     typedef const T& const_reference; 
     typedef T   value_type; 

     // rebind CTestInstAllocator to type U 
     template <class U> 
     struct rebind { 
      typedef CTestInstAllocator<U> other; 
     }; 

     // return address of values 
     pointer address (reference value) const { 
      return &value; 
     } 
     const_pointer address (const_reference value) const { 
      return &value; 
     } 

     /* constructors and destructor 
     * - nothing to do because the CTestInstAllocator has no state 
     */ 
     CTestInstAllocator() { 
     } 
     CTestInstAllocator(const CTestInstAllocator&) { 
     } 
     template <class U> 
     CTestInstAllocator (const CTestInstAllocator<U>&) { 
     } 
     ~CTestInstAllocator() { 
     } 

     // return maximum number of elements that can be allocated 
     size_type max_size() const { 
      return std::numeric_limits<size_t>::max()/sizeof(T); 
     } 

     // pvAllocate but don't initialize num elements of type T by using our own memory manager 
     pointer allocate (size_type num) { 
      /** 
      * pvAllocate memory custom memory allocation scheme 
      */ 
      return(pointer)(CPfmTestInstMemManager::pvAllocate(num*sizeof(T))); 
     } 
     // initialize elements of allocated storage p with value value 
     void construct (pointer p, const T& value) { 
      // initialize memory with placement new 
      new((void*)p)T(value); 
     } 

     // destroy elements of initialized storage p 
     void destroy (pointer p) { 
      // destroy objects by calling their destructor 
      p->~T(); 
     } 
     // vDeallocate storage p of deleted elements 
     void deallocate (pointer p, size_type num) { 
      /** 
      *Deallocate memory with custom memory deallocation scheme 
      */ 
      CPfmTestInstMemManager::vDeallocate((void*)p); 
     } 
    }; 

    // return that all specializations of this CTestInstAllocator are interchangeable 
    template <class T1, class T2> 
    bool operator== (const CTestInstAllocator<T1>&, 
     const CTestInstAllocator<T2>&) { 
      return true; 
    } 
    template <class T1, class T2> 
    bool operator!= (const CTestInstAllocator<T1>&, 
     const CTestInstAllocator<T2>&) { 
      return false; 
    } 
} 

Hãy lưu ý đặc biệt ở những dòng này:

/** 
* pvAllocate memory custom memory allocation scheme 
*/ 
return(pointer)(CPfmTestInstMemManager::pvAllocate(num*sizeof(T))); 

// vDeallocate storage p of deleted elements 
void deallocate (pointer p, size_type num) { 
/** 
*Deallocate memory with custom memory deallocation scheme 
*/ 
CPfmTestInstMemManager::vDeallocate((void*)p); 

Đây là nơi mà bạn gọi mới của bạn và xóa hoạt động trên heap của bạn.

Tôi có thể cung cấp cho bạn một ví dụ về cách xây dựng một số trình quản lý bộ nhớ cơ bản để giúp bạn thêm.

+0

Vì vậy, bạn đang nói không có cách nào để nói với STL sử dụng một cấp phát tùy chỉnh trên toàn cầu; bạn phải chắc chắn rằng khi bạn sử dụng một loại stl, bạn xác định nó với phân bổ tùy chỉnh. đúng? – OSH

+0

@OrenS. Vâng cho các trình biên dịch cụ thể, có thể có một lựa chọn nhưng tôi đang nói từ kinh nghiệm của tôi, một mình. Tôi đã ở cùng chỗ với OP và phải làm điều này. Chỉnh sửa câu trả lời đã sửa. – FailedDev

+0

@FailedDev, tôi thấy trang đó trước khi đăng ở đây và hy vọng. Nếu tôi có thể tìm ra cách làm cho người phân bổ tùy ý của tôi là người cấp phát 'mở rộng', tôi sẽ là vàng. Tôi cũng không biết cách làm thế. Nếu bạn biết điều đó, tôi sẽ đặt tên cho con chó tiếp theo của tôi là "FailedDev" ... – Reilly

6

Bạn có thể hưởng lợi từ việc sử dụng EASTL (Enterprise Arts STL (một phần) thực hiện)

EASTL -- Electronic Arts Standard Template Library

này được dành cho phát triển nhúng/trò chơi, trong môi trường nơi global heap is really scarce, non-existent or problematic in general.

Mô hình phân bổ của EASTL được lấy cảm hứng từ (hoặc tương tự như?) Các ý tưởng trong ấn phẩm Towards a Better Allocator Model nổi tiếng (PDF).

EASTL tự vay tốt cho các nhà phân bổ tùy chỉnh. Thực tế, nó không giao hàng với người cấp phát, do đó, việc cung cấp (tối thiểu) là yêu cầu để thậm chí giúp bạn đăng ký liên kết.

Đây là repo github cho EASTL: https://github.com/paulhodge/EASTL

+0

Đây là một giải pháp có thể, mặc dù tôi phải chỉnh sửa EASTL hoặc thư viện của tôi do các không gian tên std và eastl. – Reilly

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