我有一個程序(全碼here),其圍繞所述第四萬六千迭代退出:C++程序退出時沒有錯誤。如何調試?
{
PROCESSER<MONO_CONT> processer;
c_start = std::clock();
for (unsigned long long i = 0; i < iterations; i++) {
BloombergLP::bdlma::BufferedSequentialAllocatoralloc(pool, sizeof(pool));
MONO_CONT* container = new(alloc) MONO_CONT(&alloc);
container->reserve(elements);
processer(container, elements);
}
c_end = std::clock();
std::cout << (c_end - c_start) * 1.0/CLOCKS_PER_SEC << " ";
}
在這種情況下,MONO_CONT
是vector<string, scoped_allocator_adaptor<alloc_adaptor<BloombergLP::bdlma::BufferedSequentialAllocator>>>
。 我的理解是,scoped_allocator_adaptor
將確保提供的分配器將用於分配正在傳入的字符串,從而確保在每次循環迭代結束時取消分配字符串(避免@ 1201ProgramAlarm針對該問題的建議)。 alloc_adapter
只是一個使Bloomberg分配器符合正確接口的包裝。
PROCESSER
是以下模板函數對象,只是執行模板容器上的一些基本操作,MONO_CONT
:
template<typename DS2>
struct process_DS2 {
void operator() (DS2 *ds2, size_t elements) {
escape(ds2);
for (size_t i = 0; i < elements; i++) {
ds2->emplace_back(&random_data[random_positions[i]], random_lengths[i]);
}
clobber();
}
};
注意escape
和clobber
只是一些魔法做什麼比擊敗優化外(見this talk如果你有興趣)。 random_data
只是包含垃圾的char
的數組。 random_positions
將有效指數定義爲random_data
。 random_lengths
定義了從random_positions
中相應位置開始的有效字符串長度(不會超出垃圾數據的末尾)。
我有一個運行的確切迭代次數相同類似的代碼,而不會失敗:
{
PROCESSER<MONO_CONT> processer;
c_start = std::clock();
for (unsigned long long i = 0; i < iterations; i++) {
BloombergLP::bdlma::BufferedSequentialAllocator alloc(pool, sizeof(pool));
MONO_CONT container(&alloc);
container.reserve(elements);
processer(&container, elements);
}
c_end = std::clock();
std::cout << (c_end - c_start) * 1.0/CLOCKS_PER_SEC << " ";
}
兩個片段之間的主要區別在於,第一,我是new
荷蘭國際集團的集裝箱進入分配器,然後將分配器傳遞給容器,依靠分配器的銷燬來釋放容器的所有內存(而不必實際調用容器本身的析構函數)。在第二個片段中,我允許在循環的每次迭代結束時通過超出範圍來更自然地破壞容器。
我正在用Clang構建它,運行在Debian的Docker容器中。關於這個問題可能是什麼或者我該如何開始調試的建議?
第一個示例使用'placement-new'。那麼對析構函數的顯式調用在哪裏? https://isocpp.org/wiki/faq/dtors#placement-new – PaulMcKenzie
@PaulMcKenzie據我所知,它被定義爲不調用析構函數,因爲分配器的析構函數清理內存,我從來沒有訪問內存處理後的容器被丟棄。看看第3章的最後3段,瞭解我爲什麼這樣做的更多細節:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0089r0.pdf – GBleaney
如果您擔心分配器效率問題,可以考慮在循環外部創建'MONO_CONT'對象,在每次迭代後清空(),然後'reserve()'達到高水位,很少需要進行任何分配。 –