在 esp32 上分配向量后堆损坏
Corrupt heap after allocating vector on esp32
我正在尝试在 esp32-cam 上计算光流(基于 lucas kanade)。
我试图通过仅对数组的 2 个小缓冲区进行操作来节省内存。我仍然有错误损坏堆:
test0
bfore allocate out conv
after allocate out conv
bfore allocate out conv
after allocate out conv
bfore allocate out conv
after allocate out conv
bfore allocate out conv
CORRUPT HEAP: multi_heap.c:432 detected at 0x3fff7114 abort() was
called at PC 0x40090a7f on core 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);
...
}
显然,泄漏来自我在 conv(fy, ...)
的第二次调用期间由 fy
分配的第二个缓冲区,当它分配为向量时。
我做错了什么?
由于w
和h
不同,transpose
将访问和写入越界内存。
根据您的评论,您有 w
96 和 h
大约 48。transpose
中 swap
的第二个参数将访问最多 f[w * (w - 1) + h * (h - 1)]
超过了您分配的 w * h
个元素。这将更改尚未分配的内存,并且在您的情况下会破坏您的库用于跟踪已分配内存的数据(仅在分配空闲期间检测到,并且可能无法立即检测到)。
解决方案涉及重写 transpose
以正确转置矩形矩阵。 (这涉及交换返回矩阵的 w
和 h
。)
我正在尝试在 esp32-cam 上计算光流(基于 lucas kanade)。 我试图通过仅对数组的 2 个小缓冲区进行操作来节省内存。我仍然有错误损坏堆:
test0
bfore allocate out conv
after allocate out conv
bfore allocate out conv
after allocate out conv
bfore allocate out conv
after allocate out conv
bfore allocate out conv
CORRUPT HEAP: multi_heap.c:432 detected at 0x3fff7114 abort() was called at PC 0x40090a7f on core 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);
...
}
显然,泄漏来自我在 conv(fy, ...)
的第二次调用期间由 fy
分配的第二个缓冲区,当它分配为向量时。
我做错了什么?
由于w
和h
不同,transpose
将访问和写入越界内存。
根据您的评论,您有 w
96 和 h
大约 48。transpose
中 swap
的第二个参数将访问最多 f[w * (w - 1) + h * (h - 1)]
超过了您分配的 w * h
个元素。这将更改尚未分配的内存,并且在您的情况下会破坏您的库用于跟踪已分配内存的数据(仅在分配空闲期间检测到,并且可能无法立即检测到)。
解决方案涉及重写 transpose
以正确转置矩形矩阵。 (这涉及交换返回矩阵的 w
和 h
。)