这个C#程序在没有使用showdialog()的情况下工作正常但是当我试图使用showdialog()时它会产生“系统访问冲突”异常。怪异!!
C#代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace w_CSharp_GUI_1
{
public partial class Form1 : Form
{
private String W_Addr,C_Addr,Pic_Addr="lol";
[DllImport("face_proj_trial_dll.dll")]
public static extern string f_detect(string path);
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog2 = new OpenFileDialog();
openFileDialog2.ShowDialog(this);
Pic_Addr = (f_detect("C:\\pic.jpg"));
textBox1.Text = Convert.ToString(Pic_Addr);
}
}
}
C ++代码:
#include "face_detect_DLL.h"
extern "C" __declspec(dllexport) char* _stdcall f_detect(char* path)
{
return path;
}
答案 0 :(得分:1)
这一点都不奇怪。您正在返回实际由C#marshaller创建的C字符串。然后编组人员试图释放那两次记忆。一旦作为返回值,一次为参数传递给DLL。第一个空闲将失败,因为内存未分配给C#marshaller假定的分配器。
无论如何,您根本不想从DLL返回char*
。我不确定你真正想做什么,但字符串P / invokes的正常模式是:
string
,在C ++中将它们声明为char*
。StringBuilder
。在调用之前分配缓冲区并使用MarshalAs
。网络上有很多关于这种模式的例子。答案 1 :(得分:1)
返回字符串的函数是内存管理问题。必须释放字符串的内存。 pinvoke marshaller将在返回的字符串上调用CoTaskMemFree()。这会在Vista上崩溃,因为字符串没有用CoTaskMemAlloc分配,所以在XP上默默泄漏内存。
您需要将返回类型声明为IntPtr以防止编组器执行此操作。并使用Marshal.PtrToStringAnsi()自行编组。这解决了崩溃而不是内存泄漏。您需要将函数声明为void f_detect(const char * path,char * somevalue,size_t somevaluebuffersize),以便调用者可以传递自己的缓冲区。管理方的StringBuilder。