OpenCV:将 setDefaultAllocator() 与自定义分配器一起使用会调用 allocate() 但不会调用 deallocate() - 为什么?

问题描述 投票:0回答:1

我正在尝试将自定义分配器与 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 毫秒)

c++ opencv memory-management
1个回答
0
投票

我终于找到了问题所在。 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);
            }
        }
© www.soinside.com 2019 - 2024. All rights reserved.