Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Debugging in Visual Studio without Pdb files (C++ Access Voilation)

I built OpenCV binaries(.dll) using Cmake & visual studio which generated .pdb file which helped me to find the issue in code (Partially!)

How this Crash is being caused. .
I'm using a software with which we can set internet download speed limit (transfer rate) for any particular program.

Now if i connect IP camera to the code below, i noticed that my app needs around 100Kb/s of internet usage (transfer rate) - only then i can watch live stream seamlessly. Lets say i cut down (set) my application internet usage to 10Kb/s [This is the reason behind crash] in this case, i should be able to see a new frame once in 4+ seconds.

I'm getting access violation error probably because (cap>>img;) cap is trying to reach a location in ram & get the frame but there is no frame YET because its still being downloaded due to low internet speed.
Clearly the pointer is reaching some location in ram to grab a frame which is not yet present.

Some interesting behaviour . . .

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;
      }
    }
}

If i use the entire code in same class (within same header file), there is no problem at all(new frame is displayed after 4+ seconds without crashing the program) but if i put the code into a separate class(different header file), then call the function to open camera from a class object, then it crashes if internet speed is cut down.
weird behavior - if i debug step by step, it never crashes!

when i build opencv library with ffmpeg , i get .pdb file only for opencv (opencv_world310.pdb)- so no issue debugging using call stack but i do not get pdb for ffmpeg (because Opencv_ffmpeg.dll is precompiled and that is where its crashing)

hence its getting hard to debug, building ffmpeg doesn't produce pdb file cause its built using MSYS
so is it possible to debug with what we have?

I'm including snapshot from visual studio debugging, some of the variables that will help in understanding:

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

Exception thrown at 0x0A0AF6F0 (opencv_ffmpeg310.dll) in Sample.exe: 0xC0000005: Access violation reading location 0x00000020. If there is a handler for this exception, the program may be safely continued.

in source code i included below line & compiled & used it in project - didn't work, crashed again! if(ffmpegCapture) - null pointer check

can we make some changes at line 214 in [cap_ffmpeg.cpp] to avoid crash?
other header files are just one folder up.

Update: I noticed that program crashes immediately when i limit internet consumption speed. I'm using C++/Cli(winforms, target dot net Framework = 4.6), i have CameraClass (in separate header file) & main function in (separate header file)
Main function has below code

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

i cannot create non manged object type within managed class, so i put native types(Opencv variables) into separate namespace like below, so that i can use within this class. probably i have to use interior pointers?

#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()
    {


    }
.
.
.
.
};
}

definitely clash between .net memory handling & C++ memory handling?

like image 571
Prakash M Avatar asked Nov 29 '16 13:11

Prakash M


1 Answers

You can declare a unmanaged class. Have a pointer to it from the managed class.

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();
        };
}

If the dll was built on MSYS, you can use addr2line command to transform the address inside the DLL to the source line or else use unmanaged variable in managed class's function.

like image 81
Suraksha Ajith Avatar answered Oct 19 '22 12:10

Suraksha Ajith