[c++] 内存管理

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创建的数据,使内存占用率不断上升最终导致死机
     #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;
     }
    
    修改方法,在类中区别对待引用和克隆,通过加入两种不同的方法,这里我加入了operator=来赋值保证引用类不被释放,而用set来赋值克隆类保证在栈弹出的时候调用析构函数,从而避免了可能出现的内存堆积和非法访问
       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;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 内存分配方式 在C++中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。 在栈上创建...
    showaichuan阅读 328评论 0 2
  • 为什么进行内存管理? 由于移动设备的内存极其有限,所以每个APP所占的内存也是有限制的,当app所占用的内存较多时...
    天天想念阅读 908评论 1 7
  • 前言 之前的两篇拙文C语言-内存管理基础、C语言-内存管理深入 介绍了关于C语言在内存管理方面的相关知识。但是对于...
    老板娘来盘一血阅读 3,774评论 25 36
  • 1、内存分配方式 在C++中,内存分为5个区,分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。 堆:new...
    星期八我一定好好读书阅读 160评论 0 0
  • 内存管理是我们在编程时经常遇到的问题,而关于内存管理的问题往往会导致我们无从下手,这篇随笔是我阅读《高质量C++》...
    yangqi916阅读 1,251评论 0 4