Создание нового объекта уничтожает старый объект с другим именем в C ++ - PullRequest
1 голос
/ 17 мая 2010

Первый вопрос здесь!

Итак, у меня возникли некоторые проблемы с указателями в 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);
    };
[...]
};

Ответы [ 2 ]

8 голосов
/ 17 мая 2010

Вам необходимо выяснить разницу между объектами и указателями на объекты.

Ваш CameraManager содержит vector из Camera, поэтому вы должны ожидать, что ваши камеры будут скопированы по мере расширения вектора. Это означает, что копии будут созданы, а старые копии будут уничтожены в определенные моменты времени существования контейнера.

Этот вызов помещает копию параметра (камера указывает на camera1) в вектор.

cameras.push_back(*camera1);

Когда второй Camera вставляется в вектор, уничтожается не Camera, на который указывает camera1, а копия этого Camera, которая была помещена в vector. Кстати, у вас есть утечка памяти (и объекта), так как camera1 указывает на объект, который вы динамически выделяли с помощью new, но который вы не delete.

Звучит так, как будто вы не готовы к копированию объектов Camera. Возможно, вам лучше использовать контейнер с указателями (или умными указателями, чтобы помочь с чистым освобождением), или вы можете изменить способ работы класса Camera, чтобы он корректно справлялся с копированием. Не видя класс Camera, трудно понять, какой из них более уместен.

1 голос
/ 18 мая 2010

Вы храните необработанные указатели в своем классе Camera, но не определяете конструктор копирования или оператор присваивания (оба из которых std::vector требуют, чтобы вышеописанное работало правильно). Таким образом, вы получаете сгенерированные компилятором версии, которые делают поверхностную копию.

В результате cameras.push_back(*camera1); вы фактически создаете временный объект, который уничтожается после возврата push_back. Этот временный деструктор высвободит ресурсы, выделенные вами в операторе Camera *camera1 = new Camera(NodeInfo,1, -44,0,0);, а экземпляр в векторе будет иметь указатели на недопустимые ресурсы.

Вам необходимо либо не сохранять значение Camera в векторе (использовать какой-либо общий указатель) и явно помечать тип как некопируемый / назначаемый, либо вы должны предоставить необходимую семантику копирования / назначения. *

Кроме того, не говоря уже о том, что у вас есть утечка camera1 и camera2.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...