【发布时间】:2021-12-16 10:51:14
【问题描述】:
我是 C++ 新手,我需要将列表容器用于我的基于 3D 标记的分水岭函数。但是当我使用列表容器时会遇到奇怪的错误。我可以知道我的代码有什么问题吗?
非常感谢!
我使用列表向量来保存等待搜索像素索引。
我是这样声明变量的(GVInt32就是int32_t):
vector<list<GVInt32>> toSearchList;
而我使用了list的这两种操作:
- 在列表末尾添加新的等待搜索索引
toSearchList[cnt].push_back(newidx);
- 删除列表中间的搜索元素(
it是list<GVInt32>::iterator):
it = toSearchList[cnt].erase(it);
但我得到两种错误:
-
malloc(): memory corruption当我这样做时toSearchList[cnt].push_back(newidx); -
当我在调试器中检查变量时,列表末尾出现不可访问的元素:
[Not accessible elements][1]
https://i.stack.imgur.com/flJg3.png
IDE是QT creator 4.15.2
系统是Ubuntu 18.04
完整代码
分水岭_wz.cpp:
#include "watershed_wz.h"
WaterShed_WZ::WaterShed_WZ()
{
}
array<GVInt32, 6> WaterShed_WZ::getNeighbor_WZ(const GVInt32 idx, const GVInt32 width, const GVInt32 height, const GVInt32 thick) {
GVInt32 SLICE = width * height;
GVInt32 z = idx / SLICE;
GVInt32 y = (idx%SLICE) / width;
GVInt32 x = idx % width;
array<GVInt32, 6> nIndex;
nIndex[0] = (x == 0) ? -1 : (idx - 1);
nIndex[1] = ((x + 1) == width) ? -1 : (idx + 1);
nIndex[2] = (y == 0) ? -1 : (idx - width);
nIndex[3] = ((y + 1) == height) ? -1 : (idx + width);
nIndex[4] = (z == 0) ? -1 : (idx - SLICE);
nIndex[5] = ((z + 1) == thick) ? -1 : (idx + SLICE);
return nIndex;
}
void WaterShed_WZ::Watershed3D_WZ(
const Mat im,
const GVInt32 width,
const GVInt32 height,
const GVInt32 thick,
GVInt32* label,
const vector<vector<GVInt32>> marker)
{
//<Parameter>
//<image> the image for watershed
//<width> the width of the image
//<height> the height of the image
//<thick> the thick of the image
//<label> the map to save result. need to allocate memory before use watershed
//<marker> the marker's index
// const GVByte* image=im.data;
auto t0 = chrono::high_resolution_clock::now();
QTextStream out(stdout);
// const GVInt32 SZ_slice = width * height;
// const GVInt32 SZ = SZ_slice * thick;
const GVInt32 markerNum = marker.size();
// create toSearchList. Saved pixel connected to labeled pixels and wait to search
vector<list<GVInt32>> toSearchList;
toSearchList.resize(markerNum);
// set label to INIT (unsearched)
// ::memset(label, -1, sizeof(GVInt32) * SZ);
// initialize
array<GVInt32, 6> nIdx;
for (size_t i = 0; i < markerNum; i++)
{
for (GVInt32 idx : marker[i])
{
// initialize label (which can be considered as a map of pointer to labelBar)
label[idx] = i + 1;
nIdx = getNeighbor_WZ(idx, width, height, thick);
for (GVInt32 newidx : nIdx)
{
if (newidx != -1)
{
if (label[newidx] == -1) {
toSearchList[i].push_back(newidx);
label[newidx] = -2;
}
}
}
}
}
//watershed
GVByte h;
GVInt32 idx;
for (int h_cnt = 0; h_cnt < (1+(int)GV_BYTE_MAX); h_cnt++) // water height
{
h = (GVByte)h_cnt;
for (GVInt32 cnt = 0; cnt < markerNum; cnt++) { // for each marker
list<GVInt32>::iterator it = toSearchList[cnt].begin();
while (!toSearchList[cnt].empty())
{
// for each pixel connected to the cnt-th labeled region
idx = *it;
// if this pixel is higher than water, ignore it
if (im.at<unsigned char>(idx) > h)
{
++it;
if(it == toSearchList[cnt].end())
{
break;
}
else
{
continue;
}
}
// this pixel is lower than water, assign it
label[idx] = cnt + 1;
// L.at<int>(idx)=cnt + 1;
// add new neighbor
nIdx = getNeighbor_WZ(idx, width, height, thick);
for (GVInt32 newidx : nIdx)
{
if (newidx != -1)
{
if (label[newidx]== -1) {
toSearchList[cnt].push_back(newidx);
label[newidx] = -2;
// L.at<int>(newidx)=-2;
}
}
}
// erase searched pixel
it = toSearchList[cnt].erase(it);
if(it == toSearchList[cnt].end())
{
break;
}
else
{
continue;
}
}
}
}
auto t1 = chrono::high_resolution_clock::now();
auto dt = 1.e-9 * chrono::duration_cast<std::chrono::nanoseconds>(t1 - t0).count();
out << "Watershed used " << dt << " seconds.\n\n" << Qt::endl;
}
分水岭_wz.h:
#ifndef WATERSHED_WZ_H
#define WATERSHED_WZ_H
#define _USE_MATH_DEFINES
#include <vector>
#include <array>
#include <list>
#include <opencv2/core.hpp> //basic building blocks of opencv
#include <opencv2/imgcodecs.hpp> // image io
#include <opencv2/highgui.hpp> //image display
#include <QDebug>
#include <QTextStream>
#include <chrono>
using namespace std;
using namespace cv;
typedef unsigned char GVByte;
typedef int32_t GVInt32;
//typedef uint32_t GVInt32U;
const GVByte GV_BYTE_MAX = UCHAR_MAX;
class WaterShed_WZ
{
public:
WaterShed_WZ();
static array<GVInt32, 6> getNeighbor_WZ(const GVInt32 idx, const GVInt32 width, const GVInt32 height, const GVInt32 thick);
static void Watershed3D_WZ(
const Mat im,
const GVInt32 width,
const GVInt32 height,
const GVInt32 thick,
GVInt32* label,
const vector<vector<GVInt32>> marker);
};
#endif // WATERSHED_WZ_H
【问题讨论】:
-
不看你的代码,我能看到的唯一问题是 cnt 可能不是一个有效的索引。
-
用
-g编译并在valgrind下运行。valgrind会准确地告诉您发生了哪些错误的内存操作、在哪一行以及错误访问的内存曾经是什么(在双重释放、释放后使用等情况下)。
标签: c++ list qt memory-corruption