2010-05-17 9 views
1

Première question ici! Donc, j'ai quelques problèmes avec les pointeurs dans Visual C++ 2008. J'écris un programme qui va contrôler six caméras et faire un peu de traitement sur eux afin de nettoyer les choses J'ai créé une classe Camera Manager. Cette classe gère toutes les opérations qui seront effectuées sur toutes les caméras. Ci-dessous, une classe Camera qui interagit avec chaque pilote de caméra et effectue un traitement d'image de base. Maintenant, l'idée est que lorsque le gestionnaire est initialisé, il crée deux caméras et les ajoute à un vecteur afin que je puisse y accéder plus tard. Le problème ici est que lorsque je crée la seconde caméra (camera2), le destructeur de la première caméra est appelé pour une raison quelconque, ce qui déconnecte alors la caméra.La création d'un nouvel objet détruit un objet plus ancien avec un nom différent en C++

Normalement, je suppose que le problème est quelque part dans la classe Camera, mais dans ce cas tout fonctionne parfaitement tant que je ne crée pas l'objet camera2.

Qu'est-ce qui ne va pas?

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

Qu'est-ce qui vous fait penser que camera1 est détruite? Il ne devrait pas être, basé sur ce code –

+0

En passant par le code montre que, après la création de camera2 l'exécution va dans Camera :: ~ Camera qui arrête la connexion avec la caméra physique, puis détruit l'objet. La vérification de l'ID de cette caméra montre qu'il s'agit de camera1. – Mikael

Répondre

8

Vous devez effacer la différence entre les objets et les pointeurs sur les objets.

Votre CameraManager contient un vector de Camera, vous devez donc attendre que vos caméras soient copiées à mesure que le vecteur se développe. Cela signifie que des copies seront créées et que les anciennes copies seront détruites à certains moments de la vie du conteneur.

Cet appel pousse une copie du paramètre (la caméra pointée par camera1) dans le vecteur.

cameras.push_back(*camera1); 

Lorsque la deuxième Camera est poussé dans le vecteur, il est pas le Camera pointé par camera1 qui est détruite, mais une copie de ce Camera qui a été poussé dans le vector. En note, vous avez une fuite de mémoire (et d'objet) comme camera1 points à un objet que vous avez alloué dynamiquement avec new mais que vous n'avez pas delete.

Il semble que vous n'êtes pas prêt à copier vos objets Camera. Il se peut que vous soyez mieux avec un conteneur de pointeurs (ou des pointeurs intelligents pour vous aider à effectuer une désallocation propre) ou qu'il vous soit possible de modifier la façon dont votre classe Camera fonctionne correctement pour être copiée. Sans voir la classe Camera, il est difficile de savoir lequel est le plus approprié.

+0

C'était une réponse rapide! Je préférerais utiliser des pointeurs car la destruction d'objets entraînerait la déconnexion des caméras (bien que cela puisse être évité en déplaçant le code de déconnexion dans une fonction séparée). J'ai aussi mis à jour la question avec Camera.h et Camera.cpp! – Mikael

+0

@Mikael: En regardant votre classe 'Camera', vous avez peut-être raison. Il peut être plus facile d'utiliser des pointeurs ou des pointeurs intelligents pour gérer vos instances 'Camera' que de les sécuriser. Vous devez déclarer un constructeur de copie et un opérateur d'attribution de copie pour 'Camera' et les rendre privés pour des raisons de sécurité. Si vous avez accès à boost ou à tr1, vous pouvez utiliser un 'std :: vector >'. Si vous utilisez des pointeurs bruts, vous devrez probablement rendre votre 'CameraManager' non-copiable et ajouter une simple boucle supprimant les caméras allouées dynamiquement dans le desctructor. Ce serait une option moins robuste, cependant. –

1

Vous stockez des pointeurs bruts dans votre classe Camera, mais ne définissant pas de constructeur de copie ou d'opérateur d'affectation (tous les deux pour lesquels std::vector requiert le bon fonctionnement de ce qui précède). Ainsi, vous obtenez des versions générées par le compilateur qui font une copie superficielle.

En raison de cameras.push_back(*camera1);, vous créez en fait un temporaire qui est détruit après les retours push_back. Le destructeur de ce temporaire va libérer les ressources que vous avez allouées dans l'instruction Camera *camera1 = new Camera(NodeInfo,1, -44,0,0);, et l'instance dans le vecteur aura des pointeurs vers des ressources qui ne sont plus valides.

Vous devez soit pas stocker la Camera en valeur dans le vecteur (utiliser un pointeur partagé de quelque sorte) et marquer explicitement le type comme noncopyable/assignable, ou vous devez fournir la copie nécessaire/sémantique d'affectation.

En outre, pour ne pas mentionner que vous fuyez à la fois camera1 et camera2.

Questions connexes