我在我的 C 代碼中使用了一些 C 庫。庫希望我分配一些記憶體并將指標傳遞給庫。不幸的是,事先不知道確切所需的記憶體大小,因此該庫還要求我提供具有以下簽名的 C-callback:
void* callback_realloc(void* ptr, size_t new_size);
whereptr是先前傳遞的記憶體并且new_size是所需的大小,回呼必須回傳指向新分配記憶體的指標。沒有直接的方法來存盤分配器狀態。相反,我需要以某種方式依賴指標運算,如下所示:
template<class T>
struct o_s {
std::aligned_storage_t<sizeof(T), alignof(T)> data;
};
template<class Alloc>
struct o_i: private Alloc {
std::size_t allocated_size;
const Alloc& get_allocator() const { return *this; }
};
template<class T>
struct o: public o_i, public o_s<T> {
void* ptr() {
return &data;
}
// Additionally, override class operator new and operator delete...
};
void* my_callback(void* ptr, size_t new_size) {
auto meta = static_cast<o*>(reinterpret_cast<o_s<char>*>(ptr));
// access to the allocator state ...
}
然后sizeof(o_i) initial_size分配記憶體并ptr()傳遞給 C 庫。
在這一點上,我明白我不是世界上第一個需要這種模式的人。不幸的是(而且令人驚訝的是)我在 Boost 或 STL 中沒有找到任何適合此的東西。我想使用現成的實作來避免可能的水下巖石。
uj5u.com熱心網友回復:
最簡單的解決方案是使用 , 分配記憶體std::malloc并std::realloc用作回呼。諸如此類的 C API 就是在 C 中使用這些 API 有意義的情況。
但是,您不一定必須使用std::malloc。如果需要,您可以實作自定義分配器。使用一些分配的存盤是存盤分配元資料的一種方式,它是一種有效的方式。但這也不是必需的,因為您也可以將元資料單獨存盤在類似地圖的結構中。
uj5u.com熱心網友回復:
我不認為你會在 C 中找到一種慣用的方法來做到這一點,因為這是一個 C 習語。從概念上講,您有兩種方法可以解決此問題:
- 將元資料存盤在您分配的緩沖區旁邊(正如您似乎正在做的那樣)。我覺得在這里使用雙重繼承等有點矯枉過正,當您可以分配一個 sizeof(size_t) allocation_size 的字符緩沖區并將第一部分用于元資料時。
- 根據需要分配原始緩沖區并將其回傳給 API,并使用單獨的靜態資料結構通過 ptr->allocation 大小的映射來管理它。我想這就是 malloc/realloc 在幕后所做的。
兩者都是有效的,您選擇的一個取決于您的應用程式的具體細節。在處理記憶體時,可以實際處理記憶體,無論是指標算術還是其他。重要的可能是將丑陋的部分保留在一個位置,并在 C 方面為此提供 C 風格的 API,這樣客戶端代碼就不會暴露給實作細節。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/421217.html
標籤:
上一篇:使用靜態資料成員模板時出錯
