当我使用C#DllImport C ++ dll时,我有一个问题,我使用的是visual studio 2010&检查“启用非托管代码调试”,当它运行时,始终显示消息“检测到缓冲区溢出!...已检测到缓冲区溢出已损坏程序的内部状态。程序无法安全继续执行,现在必须终止。“
这个dll是第三方供应商提供的,他们说运行这个dll没有错误,我该如何修复它?
My M ++ dll函数是,
int avc_to_avi_convert(char* chPath_avc, char* chPath_avi, int pPrivate, PROGRESS_CALLBACK progress_callback);
void avc_to_avi_close(int* pFd_avi);
typedef void (*PROGRESS_CALLBACK)(int iPercent, int pPrivate);
我在我的C#dllimport中使用它:
public delegate void PROGRESS_CALLBACK(int _iPercent, int _pPrivate);
[DllImportAttribute(@"..\xxx.dll", EntryPoint = "avc_to_avi_convert", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern unsafe int avc_to_avi_convert([MarshalAs(UnmanagedType.LPStr)] StringBuilder _inputAVC, [MarshalAs(UnmanagedType.LPStr)] StringBuilder _ouputAVI, int pPrivate, PROGRESS_CALLBACK _pg);
[DllImportAttribute(@"..\xxx.dll", EntryPoint = "avc_to_avi_close", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern unsafe void avc_to_avi_close(int pFd_avi);
private void button1_Click(object sender, EventArgs e)
{
int i = 0;
StringBuilder inputFile = new StringBuilder(Application.StartupPath + @"\avc\abc.avc");//(@"C:\avc\abc.avc");
StringBuilder outputFile = new StringBuilder(Application.StartupPath + @"\avi\abc.avi");//(@"C:\avi\abc.avi");
if (avc_to_avi_convert(
inputFile,
outputFile,
1,
progress_func) > 0) {
}
}
public void progress_func(int iProgress, int pPrivate)
{
if (iProgress == 100)
{
//success
}
else if (iProgress == -1)
{
//convert error
}
else if (iProgress == -2)
{
//Not enough disk space
}
else
{
//update progress
}
}
我将代码更改为
[DllImportAttribute(@"..\xxx.dll", EntryPoint = "avc_to_avi_convert", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)]
public static extern unsafe int avc_to_avi_convert([MarshalAs(UnmanagedType.BStr)] String _inputAVC, [MarshalAs(UnmanagedType.BStr)] String _ouputAVI, int pPrivate, PROGRESS_CALLBACK _pg);
[DllImportAttribute(@"..\xxx.dll", EntryPoint = "avc_to_avi_close", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)]
public static extern void avc_to_avi_close(ref int avi);
然后跑了,我仍然得到同样的错误。
答案 0 :(得分:2)
1。)你确定调用约定吗?试试CallingConvention.StdCall
。阅读本文:
http://blogs.msdn.com/b/adam_nathan/archive/2003/05/21/56690.aspx
2.。)为CharSet
属性尝试不同的值,并使用String
代替StringBuilder
作为路径参数。这是一个很好的参考:
http://msdn.microsoft.com/en-us/library/s9ts558h.aspx
3.)此外,avc_to_avi_close
方法应如下所示:
[DllImportAttribute("xxx.dll", EntryPoint="avc_to_avi_close")]
public static extern void avc_to_avi_close(ref int avi);
4。)我想尝试的其他事情:
CharSet
和MarshalAs
的不寻常组合。例如,您从上面的链接中了解到,Unicode
应与LPWStr
和Ansi
与LPStr
一起使用,但您当然可以尝试其他组合。unsafe
。如果您已经用尽所有其他选项,为什么不尝试编写类似于C#代码的C ++程序:
答案 1 :(得分:0)
您正在将委托传递给p / invoke,然后让垃圾收集器释放它。这会导致崩溃,因为当委托对象完成后,将释放设置为允许来自本机代码的调用的trampoline。然后本机代码调用悬空函数指针。
垃圾收集器完全不知道从本机代码中使用的任何对象。您必须在通话期间保持对代表的引用。尝试添加委托变量(不要使用创建临时的隐式转换),然后使用GCHandle
使委托保持活动状态,只要本机代码正在使用它。