C++ 使用带有特征库的自定义新处理程序
我正在尝试使用一个自定义的新处理程序来响应使用库的程序中的内存不足错误 当我解算一个实例时,我会缓存结果(一个大的动态大小向量),因此如果我需要再次解算该实例,我已经得到了结果。过一段时间后,可能会发生缓存过多实例的情况,因此计算期间内存不足。在这种情况下,我会清空缓存(或者最好删除一些实例) 我想到的最简单的方法是使用一个全局变量C++ 使用带有特征库的自定义新处理程序,c++,new-operator,eigen,C++,New Operator,Eigen,我正在尝试使用一个自定义的新处理程序来响应使用库的程序中的内存不足错误 当我解算一个实例时,我会缓存结果(一个大的动态大小向量),因此如果我需要再次解算该实例,我已经得到了结果。过一段时间后,可能会发生缓存过多实例的情况,因此计算期间内存不足。在这种情况下,我会清空缓存(或者最好删除一些实例) 我想到的最简单的方法是使用一个全局变量std::map cache,并安装一个新的处理程序来清空它(除非它已经是空的,否则它会使用默认的处理程序)。这样,当分配失败时,我的处理程序会释放一些内存并返回,因
std::map cache
,并安装一个新的处理程序来清空它(除非它已经是空的,否则它会使用默认的处理程序)。这样,当分配失败时,我的处理程序会释放一些内存并返回,因此会再次尝试分配内存
然而,似乎从未调用过这样的处理程序,而是总是抛出一个std::bad_alloc
异常
我试过这个例子。使用std::vector
时,正确调用自定义处理程序,并打印“内存分配失败,终止”。使用Eigen::VectorXi
时,我只得到一个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';
}
}
#包括
#包括
#包括
#包括
void处理程序()
{
std::cout查看egen源代码中的这个文件:egen/src/Core/util/Memory.h,看看egen在这个部门做了什么。IIRC我们在分配失败时会显式地抛出bad_alloc。如果我们需要更改某些内容,请随时写信给邮件列表。多亏了Benoit Jacob的建议,我找到了egen分配的部分内存。该函数是在Eigen/src/Core/util/memory.h
中定义的aligned\u malloc()
我发现了这一点,并相应地修改了函数aligned\u malloc()
:
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();
}
}
}
现在,当分配失败时,内存处理程序被正确地调用(可能还需要修改其他分配函数,但它们似乎都由aligned_malloc()
包装,因此签入该函数可能涵盖所有内容)
但是在这一点上,我不确定Eigen是否应该尊重新的处理程序:它从malloc()
获取内存,它不使用异常,但会通知malloc()
失败通过抛出std::bad_alloc
谢谢你的建议,我成功地实现了我想要的行为。我发布了一个新的答案和详细信息。