在没有Pdb文件的Visual Studio中进行调试(C ++ Access Voilation)

时间:2016-11-29 13:02:45

标签: c++ opencv visual-c++ memory-management c++-cli

我使用Cmake& amp;生成了OpenCV二进制文件(.dll)。 visual studio,它生成.pdb文件,帮助我在代码中找到问题(部分!)

此崩溃是如何造成的。
我正在使用一种软件,我们可以为任何特定程序设置互联网下载速度限制(传输速率)。

现在,如果我将IP摄像头连接到下面的代码,我注意到我的应用程序需要大约100Kb / s的互联网使用率(传输速率) - 只有这样我才能无缝地观看直播。 让我说我减少(设置)我的应用程序互联网使用量为10Kb / s [这是崩溃背后的原因] 在这种情况下,我应该能够在4秒多的时间内看到一个新的帧。

我遇到访问冲突错误可能是因为(cap>>img;)上限正试图到达ram&得到框架,但没有框架YET,因为它仍然被下载由于低互联网速度 显然,指针到达ram中的某个位置以抓取尚未出现的帧。

一些有趣的行为。 。

Void OpenCamera()
{
    VideoCapture cap("http://192.168.1.3:8080/video?x.xmjpeg");
    Mat img;
    while(true)
    {
      try
      {
        if(cap.isOpened()) //also tried grab + retrieve, crashes at grab
        cap>>img; //code crashes here
      }
      catch(...)
      {
        cout<<"Camera Disconnected"<<endl;
      }
    }
}

如果我在同一个类中使用整个代码(在同一个头文件中),则根本没有问题(新帧在4秒以上显示而不会导致程序崩溃)但如果我将代码放入一个单独的类中(不同的头文件),然后调用该函数从类对象打开相机,然后它崩溃如果 网速减少
奇怪的行为 - 如果我一步一步调试,它永远不会崩溃!

当我使用ffmpeg构建opencv库时,我只获取opencv(opencv_world310.pdb)的.pdb文件 - 所以没有问题调试使用调用堆栈 但是我没有获得ffmpeg的pdb(因为Opencv_ffmpeg.dll是预编译的,而且它崩溃的地方)

因此难以调试,building ffmpeg不会产生pdb文件因为它使用MSYS构建,所以是否可以使用我们的内容进行调试?

我包括来自visual studio调试的快照, 一些有助于理解的变量:

typedef int (*CvGrabFrame_Plugin)( void* capture_handle );      [cap_ffmpeg_api.cpp]
protected: void* ffmpegCapture;                                 [cap_ffmpeg.cpp]
static CvGrabFrame_Plugin icvGrabFrame_FFMPEG_p = 0;            [cap_ffmpeg.cpp]

enter image description here

  

Sample.exe中的0x0A0AF6F0(opencv_ffmpeg310.dll)抛出异常:   0xC0000005:访问冲突读取位置0x00000020。如果有   这个例外的处理程序,程序可以安全地继续。

在源代码中我包含在line&amp;编译&amp;在项目中使用它 - 没有工作,再次崩溃! if(ffmpegCapture) - 空指针检查

我们可以在[cap_ffmpeg.cpp]的第214行进行一些更改以避免崩溃吗? 其他头文件只是一个文件夹。

更新:我注意到当我限制互联网消费速度时程序立即崩溃。我正在使用C ++ / Cli(winforms,目标网络框架= 4.6),我有CameraClass(在单独的头文件中)&amp;主要功能(单独的头文件)
主要功能有以下代码

CameraClass ^CC = gcnew CameraClass();
CC->OpenCamera();

我无法在托管类中创建非管理对象类型,因此我将本机类型(Opencv变量)放入单独的命名空间中,如下所示,以便我可以在此类中使用。可能我必须使用内部指针?

#pragma once
#include"opencv2\opencv.hpp"
#include <msclr\marshal_cppstd.h>

namespace SampleApp{

    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;
    using namespace System::Threading;  
    using namespace System::IO;
    using namespace std;

   namespace
    {
        cv::VideoCapture cap[5];  //max 5 instance for this class
        cv::Mat image[5];
        cv::IplImage pic1[5];
        cv::IplImage *pic2[5];
    }

public ref class CamWindow : public WeifenLuo::WinFormsUI::Docking::DockContent
{
    public: CamWindow(void)
    {
            InitializeComponent();
    }
    Void OpenCamera()
    {


    }
.
.
.
.
};
}

.net内存处理和&amp ;; C ++内存处理?

1 个答案:

答案 0 :(得分:2)

您可以声明一个非托管类。从托管类中指向它。

public class OpenCVClass
 {
      public:
         Void OpenCamera()
           {
              VideoCapture cap("http://192.168.1.3:8080/video?x.xmjpeg");
              Mat img;
                while(true)
                  {
                     try
                     {
                       if(cap.isOpened())
                       cap>>img; 
                     }
                     catch(...)
                     {
                       cout<<"Camera Disconnected"<<endl;
                     }
                  }
             }

       public ref class managed
       {
        public:
            managed(){}
           ~managed(){}
            static OpenCVClass* unmanaged = new OpenCVClass(); 
            unmanaged->OpenCVClass();
        };
}

如果dll是在MSYS上构建的,则可以使用addr2line command将DLL中的地址转换为源代码行,或者在托管类的函数中使用非托管变量。