created by Dejavu
介绍
c++在构造过程中经常会遇到内存管理的问题,这里我讲解一些我在写kinect驱动时遇到的一些主要的内存和数据管理问题
-
栈溢出
在类内直接构建大数组导致栈溢出
这里我先构建了一个6400*4800的一维数组,在栈中#define COLS 6400 #define ROWS 4800 class DataSet { public: cv::Point3f worldPt[COLS*ROWS]; };
修改方法是要将栈中创建的大型数据,放到堆中
#define COLS 6400 #define ROWS 4800 class DataSet { public: cv::Point3f *worldPt; DataSet() : worldPt(new cv::Point[COLS*ROWS]) {} ~DataSet() {delete [] worldPt;} };
-
内存泄露
由于没有合理使用delete导致在程序运行时出现部分数据无法释放,这里是无法删除function创建的数据,使内存占用率不断上升最终导致死机
修改方法,在类中区别对待引用和克隆,通过加入两种不同的方法,这里我加入了operator=来赋值保证引用类不被释放,而用set来赋值克隆类保证在栈弹出的时候调用析构函数,从而避免了可能出现的内存堆积和非法访问#define COLS 640 #define ROWS 480 class DataSet { public: cv::Point3f *worldPt; DataSet() : worldPt(new cv::Point[COLS*ROWS]) {} ~DataSet() {delete [] worldPt;} void set(DataSet dataSet); }; DataSet function() {.....return DataSet;} void DataSet::set(DataSet dataSet) {...} main() { DataSet data1 = function(); DataSet data2 = data2; }
class DataSet{ public: cv::Mat color; cv::Mat depth; cv::Point3f *worldPt; std::vector<cv::KeyPoint> kp; cv::Mat im; DataSet() : worldPt(new cv::Point3f[ROWS*COLS]) {} ~DataSet() { delete [] worldPt; } void set(DataSet dataSet); void operator=(DataSet &dataSet); };
示例源码
- 构建基类
class DataSet{
public:
cv::Mat color;
cv::Mat depth;
cv::Point3f *worldPt;
std::vector<cv::KeyPoint> kp;
cv::Mat im;
DataSet() : worldPt(new cv::Point3f[ROWS*COLS]) {}
~DataSet() { delete [] worldPt; }
void set(DataSet dataSet);
void operator=(DataSet &dataSet);
};
//本例需要查看的函数
void DataSet::set(DataSet dataSet) {
color = dataSet.color.clone();
depth = dataSet.depth.clone();
memmove(worldPt,dataSet.worldPt,sizeof(cv::Point3f)*COLS*ROWS);
im = dataSet.im.clone();
for(int i=0;i<kp.size();i++) kp.push_back(dataSet.kp[i]);
}
void DataSet::operator=(DataSet &dataSet) {
color = dataSet.color.clone();
depth = dataSet.depth.clone();
memmove(worldPt,dataSet.worldPt,sizeof(cv::Point3f)*COLS*ROWS);
im = dataSet.im.clone();
for(int i=0;i<kp.size();i++) kp.push_back(dataSet.kp[i]);
}
- 构建子类
class DataStream : public DataSet {
private:
Freenect::Freenect freenect;
bool isSelect,isShowInfo,isCopyOperation;
MyFreenectDevice& device;
bool getData();
static void* getPthreadImg(void*);
void run_thread();
public:
Mutex imgLock;
bool isSignalLoss;
bool isCalcFeature;
std::vector<VisImg> visImg;
DataStream() : device(freenect.createDevice<MyFreenectDevice>(0)) {
device.startVideo();
device.startDepth();
run_thread();
}
~DataStream() {
device.stopVideo();
device.stopDepth();
}
bool calc_feature();
DataSet copy();
cv::Mat clone();
cv::Point3f depth_to_world(int camerax,int cameray,int depthData);
int add(cv::Mat &src,std::string name);
};
//本例需要查看的函数
DataSet DataStream::copy() {
isCopyOperation = true;
Mutex::ScopedLock lock(imgLock);
DataSet dataSet;
dataSet.color = color.clone();
dataSet.depth = depth.clone();
for(int i=0;i<ROWS*COLS;i++) dataSet.worldPt[i] = worldPt[i];
if(isCalcFeature) {
dataSet.im = im.clone();
for(int i=0;i<kp.size();i++) dataSet.kp.push_back(kp[i]);
}
isCopyOperation = false;
return dataSet;
}