2012-10-13 45 views
3

我正嘗試使用自定義新處理程序來響應在使用Eigen庫的程序中發生的內存不足錯誤。當我解決一個實例時,我緩存結果(一個大的動態的大小向量),所以如果我需要再次解決這個實例,我已經有了結果。一段時間後,可能會發生太多實例被緩存,所以在計算過程中沒有足夠的內存。在這種情況下,我會清空緩存(或者更好地移除一些實例)。與特徵庫一起使用自定義新處理程序

我想出的最簡單的方法是有一個全局變量std::map<InputType, ResultType> cache,並安裝一個新的處理程序清空它(除非它已經是空的,然後回落到默認處理程序)。通過這種方式,當分配失敗時,我的處理程序釋放一些內存並返回,因此嘗試分配內存。

但是,似乎這樣的處理程序永遠不會被調用,而總是拋出一個std::bad_alloc異常。我試過here這個例子。當使用std::vector<int>時,正確調用自定義處理程序,並打印「內存分配失敗,終止」。當使用時,我只有一個std::bad_alloc異常。

#include <Eigen/Dense> 

#include <iostream> 
#include <vector> 
#include <new> 

void handler() 
{ 
    std::cout << "Memory allocation failed, terminating\n"; 
    std::set_new_handler(nullptr); 
} 

int main() 
{ 
    std::set_new_handler(handler); 
    try { 
     while(true) { 
      const unsigned long int Size = 100000000ul; 

      // Either one of the following: 

      // new Eigen::VectorXi(Size); 
      new std::vector<int>(Size); 
     } 
    } catch (const std::bad_alloc & e) { 
     std::cout << e.what() << '\n'; 
    } 
} 

我不知道爲什麼會這樣,也許徵不使用operator new分配內存?我在文檔中找不到任何東西。有沒有辦法與Eigen一起使用這種技術?或者我必須在高級別捕獲異常,清除緩存並再次執行計算?

回答

2

感謝Benoit Jacob的建議,我追蹤了Eigen分配內存的部分。該功能是Eigen/src/Core/util/Memory.h中定義的​​。原來它不使用operator new,但它調用malloc()

我發現這個example for implementing operator new和修改的功能​​相應:

inline void* aligned_malloc(size_t size) 
{ 
    check_that_malloc_is_allowed(); 

    while (true) { 
    void *result; 
    #if !EIGEN_ALIGN 
     result = std::malloc(size); 
    #elif EIGEN_MALLOC_ALREADY_ALIGNED 
     result = std::malloc(size); 
    #elif EIGEN_HAS_POSIX_MEMALIGN 
     if(posix_memalign(&result, 16, size)) result = 0; 
    #elif EIGEN_HAS_MM_MALLOC 
     result = _mm_malloc(size, 16); 
    #elif (defined _MSC_VER) 
     result = _aligned_malloc(size, 16); 
    #else 
     result = handmade_aligned_malloc(size); 
    #endif 

    if(result || !size) { 
     return result; 
    } 

    std::new_handler currentHandler = std::set_new_handler(0); 
    std::set_new_handler(currentHandler); 

    if (currentHandler) { 
     currentHandler(); 
    } else { 
     throw_std_bad_alloc(); 
    } 
    } 
} 

現在,當分配失敗(有可能需要一併修改了其他分配函數的內存處理程序正確調用,但它看起來它們全都被​​包裹着,所以這個函數的檢查可能會涵蓋所有內容)。

但是在這一點上我不知道是否徵應履行新的處理程序:它會從內存malloc()不使用異常,但它拋出std::bad_alloc通知malloc()故障。

2

在Eigen源代碼中看看這個文件:Eigen/src/Core/util/Memory.h,看看Eigen在這個部門做了些什麼。 IIRC我們在分配失敗時明確拋出bad_alloc。如果我們應該改變某些東西,請隨意寫信給郵件列表。

+0

感謝您的建議,我設法實現了我一直在尋找的行爲。我發佈了一個包含細節的新答案。 – Claudio