这里的第一个问题!
所以,我在使用Visual C ++ 2008中的指针时遇到了一些问题。我正在编写一个程序,它将控制六个摄像头并对它们进行一些处理,以便清理我创建了一个Camera Manager类。该类处理将在所有摄像机上执行的所有操作。下面是一个Camera类,它与每个单独的相机驱动程序进行交互并进行一些基本的图像处理。
现在,我们的想法是,当管理器初始化时,它会创建两个摄像头并将它们添加到矢量中,以便我以后可以访问它们。这里的问题是,当我创建第二台摄像机(camera2)时,出于某种原因调用第一台摄像机的析构函数,然后断开摄像机的连接。
通常情况下,我认为问题出在Camera类的某个地方,但在这种情况下,只要我不创建camera2对象,一切都会完美。
出了什么问题?
CameraManager.h:
#include "stdafx.h"
#include <vector>
#include "Camera.h"
class CameraManager{
std::vector<Camera> cameras;
public:
CameraManager();
~CameraManager();
void CaptureAll();
void ShowAll();
};
CameraManager.cpp:
#include "stdafx.h"
#include "CameraManager.h"
CameraManager::CameraManager()
{
printf("Camera Manager: Initializing\n");
[...]
Camera *camera1 = new Camera(NodeInfo,1, -44,0,0);
cameras.push_back(*camera1);
// Adding the following two lines causes camera1's destructor to be called. Why?
Camera *camera2 = new Camera(NodeInfo,0, 44,0,0);
cameras.push_back(*camera2);
printf("Camera Manager: Ready\n");
}
Camera.h
#include "stdafx.h"
// OpenCV
#include <cv.h>
#include <highgui.h>
// cvBlob
#include "cvblob.h"
// FirePackage
#include <fgcamera.h>
using namespace cvb;
class Camera{
public:
int cameraID;
double x, y,z, FOVx, FOVy;
IplImage *image, *backgroundImage, *labeledImage;
CvBlobs blobs;
Camera(FGNODEINFO NodeInfo[], int camID, float xin, float yin, float zin);
~Camera();
void QueryFrame();
void ProcessFrame();
void GrabBackground();
void LoadCalibration();
void Show();
private:
// ======= FirePackage ======
CFGCamera FGCamera;
UINT32 Result;
FGNODEINFO MyNodeInfo;
UINT32 NodeCnt;
FGFRAME Frame;
// ======= Camera Configuration ======
// Trigger Settings
UINT32 nOn, nPolarity, nSrc, nMode, nParm, BurstCount, DMAMode;
// Image Settings
UINT32 AutoExposure, Shutter, Gain, Brightness, Gamma;
// Image Format Settings
UINT32 Format, Mode, Resolution, ColorFormat, FrameRate;
// Structures
UINT32 TriggerValue;
UINT32 FormatValue;
UINT32 DFormatValue;
// OpenCV Calibration matrices
CvMat *intrinsics, *distortion;
IplImage *mapx, *mapy;
void SetUpFirePackage();
void SetUpOpenCV();
};
Camera.cpp:
#include "stdafx.h"
#include "Camera.h"
Camera::Camera(FGNODEINFO NodeInfo[], int camID, float xin, float yin, float zin)
{
cameraID = camID;
x = xin;
y = yin;
z = zin;
FOVx = 42.6;
FOVy = 32.5;
MyNodeInfo = NodeInfo[cameraID];
SetUpFirePackage();
SetUpOpenCV();
// Grab the first frame
printf("Waiting for frame...\n");
QueryFrame();
};
//Destructor
Camera::~Camera()
{
// Stop the device
FGCamera.StopDevice();
// Close capture
FGCamera.CloseCapture();
// Disconnect before ExitModule
FGCamera.Disconnect();
// Exit module
FGExitModule();
cvReleaseImage(&image);
};
[...]
};
答案 0 :(得分:8)
您需要弄清楚对象和指向对象的指针之间的区别。
您的CameraManager
包含vector
Camera
,因此您必须在向量展开时复制相机。这意味着将创建副本,并在容器的生命周期中的某些点销毁旧副本。
此调用将参数的副本(camera1
指向的摄像机)推送到矢量中。
cameras.push_back(*camera1);
当第二个Camera
被推入向量时,Camera
指向的camera1
不是被销毁的,而是被推入的Camera
的副本vector
。作为旁注,您有一个内存(和对象)泄漏,因为camera1
指向您使用new
动态分配但不是delete
的对象。
听起来好像你没有准备好复制Camera
个对象。可能你最好使用一个指针容器(或智能指针来帮助清理释放),或者你可以改变你的Camera
类的工作方式来正确应对被复制。没有看到Camera
类,很难知道哪个更合适。
答案 1 :(得分:1)
您将原始指针存储在Camera
类中,但未定义复制构造函数或赋值运算符(std::vector
要求上述内容正常工作)。因此,您可以获得编译器生成的版本,这些版本可以执行浅层复制。
作为cameras.push_back(*camera1);
的结果,您实际上创建了一个在push_back
返回后被销毁的临时文件。这个临时的析构函数将释放你在语句Camera *camera1 = new Camera(NodeInfo,1, -44,0,0);
中分配的资源,向量中的实例将指向不再有效的资源。
您需要不将Camera
值存储在向量中(使用某种类型的共享指针)并明确将该类型标记为noncopyable / assignable,否则您应该提供必要的复制/赋值语义。
另外,更不用说你泄漏了camera1
和camera2
。