每个人--我这里有一个Heisenbug (只在调试器分离的情况下出现!)。似乎在非托管互操作的C#中--如果我对%TEMP%目录执行OpenCv cvSaveImage,这是可以的,但对于我尝试过的其他目录,它会抛出AccVio或挂起。以管理员身份运行,因此不会直接成为安全问题。在C# Visual Studio2010调试器下运行,它在任何目录下都可以正常工作。已分离调试器(ctrl F5) ...崩溃或挂起!好的。
如果有任何建议,我将不胜感激。我知道你们中的一些人在这个互操作层生活和呼吸,但是我没有工具&足够新的经验。我做了一个很小的复制品给你玩
必须使用默认设置从sourceforge.net/ free image processing and computer vision (cv) /opencvlibrary/安装OpenCv2.2项目
然后从http://dl.dropbox.com/u/1997638/OpenCv2.2Test.zip获取我的Visual Studio2010项目
这是一个包装器(感谢Heiko Kieüling,iib-chemnitz.de for the original!)以及一个带有注释的测试程序,这些注释可以指导您找到可重复的bug。
再一次,我将非常感谢任何建议或线索!
编辑:@Aliostad:这是整个程序(不包括包装器,它在我链接的VS项目中)
static void Main(string[] args)
{
CvLib.CvNamedWindow("TestWindow2", CvLib.CV_WINDOW_AUTOSIZE);
var img = CvLib.CvCreateImage(
CvLib.CvSize(256, 256),
depth: 8,
channels: 3);
var pts = new[] {
CvLib.CvPoint(0, 0),
CvLib.CvPoint(0, 255),
CvLib.CvPoint(255,255),
CvLib.CvPoint(255, 0)
};
CvLib.CvFillConvexPoly(
img: ref img,
pts: ref pts[0],
npts: 4,
color: CvLib.CV_RGB(0, 0, 255),
line_type: 8,
shift: 0);
CvLib.CvCircle(
img: ref img,
center: CvLib.CvPoint(128, 128),
radius: 20,
color: CvLib.CV_RGB(255, 255, 0),
thickness: 5,
line_type: 8,
shift: 0);
CvLib.CvShowImage(
name: "TestWindow2",
image: ref img);
var tempDirectory = Environment.GetEnvironmentVariable("TEMP");
var path = tempDirectory + @"\test.png";
CvLib.CvSaveImage(
path: path,
img: ref img);
MessageBox.Show("Click OK to exit");
CvLib.CvDestroyAllWindows();
}如果将"path“更改为其他值,则会在未附加调试器时导致崩溃或挂起。
编辑:@Aliostad --这是cvSaveImage的互操作代码。我确信我不理解MarshalAs属性,我猜这就是问题的根源
public static void CvSaveImage(string path, ref IplImage img)
{
cvSaveImage(path, img.ptr);
}
[DllImport(HIGHGUI_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
private static extern void cvSaveImage([MarshalAs(UnmanagedType.LPStr)] String filename, IntPtr img);发布于 2010-12-25 01:34:19
这是原生cvSaveImage()函数的声明,从Highgui.h检索:
CVAPI(int) cvSaveImage( const char* filename, const CvArr* image,
const int* params CV_DEFAULT(0) );这是它的pinvoke声明,从包装器HighGui.cs中检索:
[DllImport(HIGHGUI_LIBRARY, CallingConvention = CallingConvention.Cdecl)]
private static extern void cvSaveImage([MarshalAs(UnmanagedType.LPStr)] String filename, IntPtr img);请注意,本机声明有三个参数,而pinvoke声明只有两个。可以从C++程序调用本机函数,并且只传递两个参数,编译器会自动将默认值应用于第三个参数。但对于pinvoke编组程序,这不是这样的,它甚至不知道第三个参数是否存在。
结果是本机函数获得params参数的任意值。当它意外地为0时,它会起作用。但是,该函数还有40亿种其他方法来获取非空参数,并在取消引用指针时直接访问冲突。失败将是随机的。
通过编辑pinvoke声明并添加一个IntPtr作为第三个参数来解决这个问题。在C#代码中传递IntPtr.Zero。
这是一个相当基本的错误,预计这个包装器会有更多的麻烦。
https://stackoverflow.com/questions/4513787
复制相似问题