Поврежденная куча после размещения вектора на esp32 - PullRequest
0 голосов
/ 17 апреля 2020

Я пытаюсь вычислить оптический поток (на основе lucas kanade) на камере esp32. Я пытался сэкономить память, работая только на 2 небольших буфера массива. У меня все еще есть ошибка поврежденной кучи:

test0

bfore, чтобы выделить conv

после выделения out conv

bfore, выделить out conv

после выделения конв

b перед выделением кон

после выделения кон

bпредоставление кон

ПОВЕРХНАЯ КАРТА: multi_heap. c: 432, обнаруженный в 0x3fff7114 abort () был вызван в P C 0x40090a7f на ядре 0

Вот мой код, составленный из 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, ...), когда он выделяется как вектор. Что я делаю не так?

1 Ответ

1 голос
/ 17 апреля 2020

Если w и h не совпадают, transpose получит доступ и запишет в недопустимую память.

Из вашего комментария вы получите w при 96 и h около 48. Второй параметр swap в transpose будет иметь доступ к f[w * (w - 1) + h * (h - 1)], который превышает w * h элементы, которые вы выделили. Это изменит память, которая не была выделена, и в вашем случае повреждает данные, которые ваша библиотека использует для отслеживания выделенной памяти (которая обнаруживается только во время выделения свободной и может не обнаруживаться сразу).

Решение включает переписывание transpose для правильной транспонирования прямоугольной матрицы angular. (Это включает в себя замену w и h для возвращенной матрицы.)

...