2010-05-17 20 views
1

第一個問題在這裏!我正在寫一個程序,它將控制六臺​​攝像機,並對它們進行一些處理,以便清理東西,我創建了一個攝像頭管理器類。該課程將處理所有相機上將執行的所有操作。下面是一個Camera類,它與每個單獨的相機驅動程序交互並進行一些基本的圖像處理。創建一個新對象在C++中銷燬具有不同名稱的舊對象

現在,想法是當管理器初始化時,它會創建兩個攝像機並將它們添加到矢量中,以便稍後可以訪問它們。這裏的問題是,當我創建第二個攝像頭(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

是什麼讓你覺得camera1被毀?它不應該是,根據此代碼 – 2010-05-17 18:10:01

+0

單步執行代碼表明,在創建camera2後,執行進入Camera ::〜Camera,它關閉與物理相機的連接,然後銷燬該對象。檢查該相機的ID顯示它是camera1。 – Mikael 2010-05-17 18:31:40

回答

8

您需要清除對象和指向對象的指針之間的差異。

您的CameraManager包含vectorCamera所以您必須期望您的相機在矢量展開時被複制。這意味着將創建副本並在容器的整個生命週期中的某些點銷燬舊副本。

此調用將參數的副本(由camera1指向的攝像頭)推入矢量中。

cameras.push_back(*camera1); 

當第二Camera被推入矢量它不是Camera指向camera1被破壞,但這Camera的副本被推入vector。作爲一個方面說明,您有一個內存(和對象)泄漏,因爲camera1指向您動態分配的對象,但您不需要delete

聽起來好像您沒有準備好要複製您的Camera對象。這可能是因爲您最好使用指針容器(或者智能指針來幫助清理重新分配),或者您可能會改變類的工作方式以正確處理複製。沒有看到Camera類,很難知道哪個更合適。

+0

這是一個快速的答案!我更喜歡使用指針,因爲銷燬對象會導致相機斷開連接(儘管可以通過將斷開連接代碼移入單獨的功能來避免)。我已經用Camera.h和Camera.cpp更新了這個問題! – Mikael 2010-05-17 18:46:01

+0

@Mikael:看看你的「攝像頭」課,你可能是對的。使用指針或智能指針來管理你的'Camera'實例可能比使它們更安全。您應該爲'Camera'聲明一個拷貝構造函數和一個拷貝賦值操作符,並且爲了安全而將它們私有化。如果你有權訪問boost或tr1,你可以使用'std :: vector >'。如果您使用原始指針,則可能需要讓「CameraManager」不可複製,並添加一個簡單的循環,刪除分析器中動態分配的相機。不過,這將是一個不太健壯的選擇。 – 2010-05-17 18:55:20

1

您正在將raw指針存儲在您的Camera類中,但未定義複製構造函數或賦值運算符(上述兩項都需要上述工作才能正常工作)。所以,你得到編譯器生成的版本,做一個淺拷貝。

作爲cameras.push_back(*camera1);的結果,您實際上創建了一個在push_back返回後被銷燬的臨時設備。這個臨時的析構函數將釋放你在語句Camera *camera1 = new Camera(NodeInfo,1, -44,0,0);中分配的資源,並且向量中的實例將指向不再有效的資源。

您需要按照向量中的值存儲Camera(使用某種類型的共享指針)並明確標記該類型爲不可複製/可賦值,或者您應該提供必要的複製/分配語義。

另外,更不用說你漏了camera1camera2