我正在尝试将自定义分配器与 opencv 一起使用。我尝试测试它,但这种行为对我来说没有意义。 我在某个范围内创建了一个 CV 垫。我可以看到 allocate() 内部的打印,但看不到 deallocate() 内部的打印。
有什么解释吗?
#include "gtest/gtest.h"
#include "opencv2/opencv.hpp"
class CvMatAllocatorTest : public ::testing::Test
{
protected:
};
class UserMatDebugAllocator : public cv::MatAllocator
{
public:
UserMatDebugAllocator()
{
m_defaultAllocator = cv::Mat::getDefaultAllocator();
m_stdAllocator = cv::Mat::getStdAllocator();
std::cout << "UserMatDebugAllocator: constructor" << std::endl;
}
~UserMatDebugAllocator() override
{
std::cout << "UserMatDebugAllocator: destructor" << std::endl;
}
cv::UMatData* allocate(int dims, const int* sizes, int type,
void* data, size_t* step, cv::AccessFlag flags, cv::UMatUsageFlags usageFlags) const override
{
std::cout << "UserMatDebugAllocator: allocate" << std::endl;
return m_defaultAllocator->allocate(dims, sizes, type, data, step, flags, usageFlags);
}
bool allocate(cv::UMatData* data, cv::AccessFlag accessflags, cv::UMatUsageFlags usageFlags) const override
{
std::cout << "UserMatDebugAllocator: allocate2" << std::endl;
return m_defaultAllocator->allocate(data, accessflags, usageFlags);
}
void deallocate(cv::UMatData* data) const override
{
std::cout << "UserMatDebugAllocator: deallocate" << std::endl;
return m_defaultAllocator->deallocate(data);
}
void map(cv::UMatData* data, cv::AccessFlag accessflags) const override
{
std::cout << "UserMatDebugAllocator: map" << std::endl;
return m_defaultAllocator->map(data, accessflags);
}
void unmap(cv::UMatData* data) const override
{
std::cout << "UserMatDebugAllocator: unmap" << std::endl;
return m_defaultAllocator->unmap(data);
}
void download(cv::UMatData* data, void* dst, int dims, const size_t sz[],
const size_t srcofs[], const size_t srcstep[],
const size_t dststep[]) const override
{
std::cout << "UserMatDebugAllocator: download" << std::endl;
return m_defaultAllocator->download(data, dst, dims, sz, srcofs, srcstep, dststep);
}
void upload(cv::UMatData* data, const void* src, int dims, const size_t sz[],
const size_t dstofs[], const size_t dststep[],
const size_t srcstep[]) const override
{
std::cout << "UserMatDebugAllocator: upload" << std::endl;
return m_defaultAllocator->upload(data, src, dims, sz, dstofs, dststep, srcstep);
}
void copy(cv::UMatData* srcdata, cv::UMatData* dstdata, int dims, const size_t sz[],
const size_t srcofs[], const size_t srcstep[],
const size_t dstofs[], const size_t dststep[], bool sync) const override
{
std::cout << "UserMatDebugAllocator: copy" << std::endl;
return m_defaultAllocator->copy(srcdata, dstdata, dims, sz, srcofs, srcstep, dstofs, dststep, sync);
}
cv::BufferPoolController* getBufferPoolController(const char* id = NULL) const override
{
std::cout << "UserMatDebugAllocator: getBufferPoolController" << std::endl;
return m_defaultAllocator->getBufferPoolController(id);
}
cv::MatAllocator* m_defaultAllocator;
cv::MatAllocator* m_stdAllocator;
};
TEST_F(CvMatAllocatorTest, cvMatAllocatorTest)
{
std::cout << "test start" << std::endl;
UserMatDebugAllocator userAllocator;
cv::Mat::setDefaultAllocator(&userAllocator);
{
cv::Mat mat(1000, 1000, CV_8UC3);
mat.at<cv::Vec3b>(500, 500) = cv::Vec3b(255, 0, 0);
}
sleep(3);
std::cout << "test end" << std::endl;
}
输出:
测试开始
UserMatDebugAllocator:构造函数
UserMatDebugAllocator:分配
测试结束
UserMatDebugAllocator:析构函数
[ 确定 ] CvMatAllocatorTest.cvMatAllocatorTest(3000 毫秒)
我终于找到了问题所在。 allocate() 是告诉 CV Mat 谁是它的分配器,稍后在调用 unmap() 时使用它。 在问题中发布的示例代码中,CV Mat 不知道 UserMatDebugAllocator 是其分配器,因此在释放期间没有调用此类中的其他函数。
将代码更改为如下使得显示 deallocate() 打印:
cv::UMatData* allocate(int dims, const int* sizes, int type,
void* data, size_t* step, cv::AccessFlag flags, cv::UMatUsageFlags usageFlags) const override
{
std::cout << "UserMatDebugAllocator: allocate" << std::endl;
cv::UMatData* ret = m_defaultAllocator->allocate(dims, sizes, type, data, step, flags, usageFlags);
if (nullptr != ret)
{
// the following line is what causes the unmap() to reach this class as well
ret->currAllocator = this;
}
return ret;
}
void unmap(cv::UMatData* data) const override
{
std::cout << "UserMatDebugAllocator: unmap" << std::endl;
if ((data->urefcount == 0) && (data->refcount == 0))
{
deallocate(data);
}
}