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

Pra*_*h M 10 c++ opencv memory-management c++-cli visual-c++

我使用Cmake和visual studio构建了OpenCV二进制文件(.dll),它生成了.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;
      }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

因此很难调试,构建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]
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

Sample.exe中的0x0A0AF6F0(opencv_ffmpeg310.dll)抛出异常:0xC0000005:访问冲突读取位置0x00000020.如果存在此异常的处理程序,则可以安全地继续该程序.

在源代码我包括下面的行和编译并在项目中使用它 - 没有工作,再次崩溃! if(ffmpegCapture) - 空指针检查

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

更新:我注意到当我限制互联网消费速度时程序立即崩溃.我正在使用C++/Cli(winforms,target dot net Framework = 4.6),我有CameraClass(在单独的头文件中)和main函数(单独的头文件)
主函数有下面的代码

CameraClass ^CC = gcnew CameraClass();
CC->OpenCamera();
Run Code Online (Sandbox Code Playgroud)

我无法在托管类中创建非管理对象类型,因此我将本机类型(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()
    {


    }
.
.
.
.
};
}
Run Code Online (Sandbox Code Playgroud)

绝对在.net内存处理和C++内存处理之间发生冲突?

Sur*_*ith 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();
        };
}
Run Code Online (Sandbox Code Playgroud)

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