C# 調用OpenCVSharp報錯“嘗試讀取或寫入受保護的內存。這通常指示其他內存已損壞”


一、描述問題

當托管代碼調用非托管代碼的時候,經常會出現如下報錯:“嘗試讀取或寫入受保護的內存。這通常指示其他內存已損壞”。

二、原因分析

由於非托管代碼的內存指針的回收是由非托管代碼自身手動完成的,而不是像托管代碼一樣有統一的垃圾回收機制,比如.NET的GC。

所以對於托管代碼的調用方來說無法控制其內存回收。以上問題的產生原因很可能是托管代碼調用了已經被回收的非托管對象。封裝

的好一點的非托管代碼一般都會有內存釋放的接口供外部調用,這樣調用方就可以管理非托管代碼的內存回收。

三、解決方法

盡量不用使用不確定的非托管代碼里面提供的對象。如果必須使用的話,實例化完成后直接使用而不要通過什么方法傳遞,委托回調等方式來

獲取里面的對象,在這些復雜未知的過程中,很可能非托管的對象已經被回收了。

四、示例說明

當使用C#調用OpenCVSharp的時候,經常會出現以上問題。

錯誤代碼如下:

1、訂閱鼠標回調方法,並將mat的指針Data作為參數傳遞給回調方法。

1   private void button15_Click(object sender, EventArgs e)
2         {
3             Mat mat = GetMat();//獲取Mat對象
4             Cv2.SetMouseCallback("輸入圖像", GetRGBCvMouseCallback, mat.Data);
5         }

2、回調方法,獲取每個點的RGB值

 1   private void GetRGBCallbackMethod(MouseEvent @event, int x, int y, MouseEvent flags, IntPtr userdata)
 2         {
 3             switch (@event)
 4             {
 5                 case MouseEvent.LButtonDown:
 6 
 7                     using (Mat mat = new Mat(Rows, Cols, _MatType, userdata))//這種方式會被內存回收,直接在這里面獲取對象
 8                     {
 9                         for (int i = 0; i < Rows; i++)
10                         {
11                             for (int j = 0; j < Cols; j++)
12                             {
13                                 Vec3b s = mat.At<Vec3b>(j, i);//獲取第i0行第i1列)  這個方法會死 嘗試讀取收保護內存
14                             }
15 
16                         }
17                     }
18                     break;
19                 default:
20                     break;
21            }

運行報錯,截圖如下:

 

 

正確代碼:

   將7行代碼Mat mat = new Mat(Rows, Cols, _MatType, userdata)改成using (Mat mat=GetMat()) ,就不會出現以上問題。

原因分析:

原因很可能是userData中回調的過程中已經被回收了,當再次使用時就會報嘗試訪問被保護的內存的錯誤。為了

防止此問題的發生,解決辦法就是重新實例化一個Mat對象,不使用可能被回收的userData數據。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM