首页 > 解决方案 > 在 esp32 上分配向量后损坏堆

问题描述

我正在尝试在 esp32-cam 上计算光流(基于 lucas kanade)。我试图通过仅对数组的 2 个小缓冲区进行操作来节省内存。我仍然有一个错误损坏堆:

测试0

在分配出转化之前

分配出转化后

在分配出转化之前

分配出转化后

在分配出转化之前

分配出转化后

在分配出转化之前

CORRUPT HEAP:multi_heap.c:432 在 0x3fff7114 检测到 abort() 在核心 0 上的 PC 0x40090a7f 上调用

这是我的代码,由 1D 卷积和转置组成,以执行单独的等效 2D 卷积:

    template<typename T>
    void
    conv(uint8_t *in, const std::vector<T> &g, const int nf) {
        //int const nf = f.size();
        int const ng = g.size();
        int const n  = nf + ng - 1;
        uint8_t *f = in;
        Serial.println("bfore allocate out conv");
        std::vector<T> out(n, T()); // memory leak CORRUPT HEAP
        Serial.println("after allocate out conv");  
        for(auto i(0); i < n; ++i) {
            int const jmn = (i >= ng - 1)? i - (ng - 1) : 0;
            int const jmx = (i <  nf - 1)? i            : nf - 1;
            for(auto j(jmn); j <= jmx; ++j) {
                out[i] += (f[j] * g[i - j]);
            }
        }
        out.erase(out.begin(), out.begin() + ng / 2 + 1);

        // Rescale to 0..255
        auto max = *std::max_element(out.begin(), out.end());
        auto min = *std::min_element(out.begin(), out.end());
        float x;
        for(auto v : out) {
            x = (v - min) * 255.0 / max;
            *(f++) = (uint8_t)x;
        }
        std::vector<T>().swap(out);
    }

    void transpose(uint8_t *f, int w, int h) {
        for(auto i(0); i < h; ++i) 
            for(auto j(0); j < w; ++j) 
                std::swap(f[w * i + j], f[w * j + i]);
    }

    void LK_optical_flow(uint8_t *src1, uint8_t *src2, uint8_t *output, int w, int h)
    {

        Serial.println("test0");

        std::vector<float> Kernel_Dy = {1, 2, 1};
        std::vector<float> Kernel_Dx = {-1, 0, 1};
        std::vector<float> Kernel_Dt = {1/3.0, 1/3.0, 1/3.0};

        uint8_t *fx = src1;
        uint8_t *fy = new uint8_t[w * h];
        uint8_t *ft = src2;

        memcpy(fy, fx, w * h * sizeof(uint8_t));

        // Sobel Dx
        conv(fx, Kernel_Dx, w*h);
        transpose(fx, w, h);
        conv(fx, Kernel_Dy, w*h);
        transpose(fx, w, h);    
        // Sobel Dy
        conv(fy, Kernel_Dy, w*h);
        transpose(fy, w, h);
        conv(fy, Kernel_Dx, w*h);  // memory leak
        transpose(fy, w, h);    
        // Dt
        //conv(src2, Kernel_Dt, w*h);
    ...
    }

显然,泄漏来自我fy在第二次调用期间分配的第二个缓冲区,conv(fy, ...)当它分配为向量时。我究竟做错了什么?

标签: c++arduinoesp32

解决方案


与不一样,将访问w和写入越界内存。htranspose

根据您的评论,您有w96 个和h大约 48 个。swapin的第二个参数transpose将访问f[w * (w - 1) + h * (h - 1)]超过w * h您分配的元素。这将更改尚未分配的内存,并且在您的情况下会破坏您的库用于跟踪已分配内存的数据(仅在分配空闲时检测到,并且可能不会立即检测到)。

该解决方案涉及重写transpose以正确转置矩形矩阵。(这涉及交换wh返回的矩阵。)


推荐阅读