C++。NET包装器:尝试读取或写入受保护的内存。这通常表示其他内存已损坏 我有一个用于非托管MFC DLL的C++ .NET包装器。此包装器由vb.net dll使用,调用到我的c#代码中。在运行时,有时包装器会引发尝试读取或写入受保护内存的异常 System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt
它似乎随机出现在我的“While”循环中。有时它在开始时,有时在中间,有时没有被抛出。 工作原理: 我的程序需要一个MFCDLL。我的程序中引用了一个wrapper.dll(c++)和一个myVbDll.dll(vb.net)。我还添加了MFC dll作为内容,因为它不是有效的COM组件。这就是它的工作原理: myprogram.exe->myVbDll.dll->wrapper.dll->myMFC.dll->myMFC函数 信息:如果我设置C++。NET包装器:尝试读取或写入受保护的内存。这通常表示其他内存已损坏 我有一个用于非托管MFC DLL的C++ .NET包装器。此包装器由vb.net dll使用,调用到我的c#代码中。在运行时,有时包装器会引发尝试读取或写入受保护内存的异常 System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt,c#,c++,memory,mfc,wrapper,C#,C++,Memory,Mfc,Wrapper,它似乎随机出现在我的“While”循环中。有时它在开始时,有时在中间,有时没有被抛出。 工作原理: 我的程序需要一个MFCDLL。我的程序中引用了一个wrapper.dll(c++)和一个myVbDll.dll(vb.net)。我还添加了MFC dll作为内容,因为它不是有效的COM组件。这就是它的工作原理: myprogram.exe->myVbDll.dll->wrapper.dll->myMFC.dll->myMFC函数 信息:如果我设置field=“无论如何”在调用MyWrappedFu
field=“无论如何”代码>在调用MyWrappedFunction之前,不会抛出错误
更新:经过多次更改后,问题仍然存在。这次我看一下如何将unicode字符串转换为Ansi。可能有什么东西要找。。。因为当您像上面那样在字符串中写入文本时,它可以工作,但是当使用ToString函数时,它就不工作了
有人能说出为什么会发生这种情况吗
我的c#程序的一部分(使用TextFieldParser从.csv文件中读取5000行以获取字段):
VB.net Dll的一部分,由我的c#程序调用:
Public Class myVbDll
Public Declare Auto Function MyWrappedFunction Lib "myWrapper.dll" (ByVal name As String, ByVal opt As Boolean) As String
End Class
Public Class myVbDll
<DllImport("Wrapper.dll", CharSet:=CharSet.Unicode)> Public Shared Function MyWrappedFunction (ByVal nom As String, ByVal opt As Boolean) As String
End Function
End Class
MFC包装的一部分,由VB.net Dll调用(错误肯定不会进入MFC Dll):
这是C++代码中的<>强>非常/强>严重错误。您正在返回局部变量的地址。由A2OLE()创建的缓冲区。它调用C++代码中的未定义行为。当您从C++代码调用这个函数时,这会有意外地发生,您可能有其他的函数调用,它覆盖了过去使用的局部变量的堆栈地址。当pinvoke函数调用时,这些几率变为零,堆栈地址将被pinvoke marshaller函数调用删除。如果这本身不会导致崩溃,那么pinvoke marshaller将确保在尝试使用CoTaskMemFree()释放字符串时崩溃
<>你必须首先修复C++代码。不,只是将指针复制到C_resultat中并不是一个解决方案
请注意,尝试拯救此函数没有多大意义。它不会做任何你在C中做不到的事情。只需为“MyFunction”函数编写一个[DllImport]属性
这是C++代码中的<>强>非常/强>严重错误。您正在返回局部变量的地址。由A2OLE()创建的缓冲区。它调用C++代码中的未定义行为。当您从C++代码调用这个函数时,这会有意外地发生,您可能有其他的函数调用,它覆盖了过去使用的局部变量的堆栈地址。当pinvoke函数调用时,这些几率变为零,堆栈地址将被pinvoke marshaller函数调用删除。如果这本身不会导致崩溃,那么pinvoke marshaller将确保在尝试使用CoTaskMemFree()释放字符串时崩溃
<>你必须首先修复C++代码。不,只是将指针复制到C_resultat中并不是一个解决方案
请注意,尝试拯救此函数没有多大意义。它不会做任何你在C中做不到的事情。只需为“MyFunction”函数编写一个[DllImport]属性。最后,我解决了这个问题
问题的真正原因是编码字符串。下面是我为改进代码所做的所有更改
如果你看到我做的可疑的事情可以改进,请随意评论
我的主要申请:
private void processImport()
{
string[] fields;
string field ;
string temp = "";
byte[] tempByte;
TextFieldParser parser = new TextFieldParser(textbox_csv.Text, System.Text.Encoding.UTF8);
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(";");
while (!parser.EndOfData)
{
fields = parser.ReadFields();
field = fields[0];
temp = RemoveDiacritics(field).ToUpper();
//this line is very important. It seems to change the Encoding of my string to Unicode.
temp = temp.Normalize(NormalizationForm.FormC);
field = myVbDll.MyWrappedFunction(temp, false);
}
parser.Close();
}
//Transforms the culture of a letter to its equivalent representation in the 0-127 ascii table, such as the letter 'é' is substituted by an 'e'
public string RemoveDiacritics(string s)
{
string normalizedString = null;
StringBuilder stringBuilder = new StringBuilder();
normalizedString = s.Normalize(NormalizationForm.FormD);
int i = 0;
char c = '\0';
for (i = 0; i <= normalizedString.Length - 1; i++)
{
c = normalizedString[i];
if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
{
stringBuilder.Append(c);
}
}
return stringBuilder.ToString().ToLower();
}
最后,我解决了这个问题
问题的真正原因是编码字符串。下面是我为改进代码所做的所有更改
如果你看到我做的可疑的事情可以改进,请随意评论
我的主要申请:
private void processImport()
{
string[] fields;
string field ;
string temp = "";
byte[] tempByte;
TextFieldParser parser = new TextFieldParser(textbox_csv.Text, System.Text.Encoding.UTF8);
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(";");
while (!parser.EndOfData)
{
fields = parser.ReadFields();
field = fields[0];
temp = RemoveDiacritics(field).ToUpper();
//this line is very important. It seems to change the Encoding of my string to Unicode.
temp = temp.Normalize(NormalizationForm.FormC);
field = myVbDll.MyWrappedFunction(temp, false);
}
parser.Close();
}
//Transforms the culture of a letter to its equivalent representation in the 0-127 ascii table, such as the letter 'é' is substituted by an 'e'
public string RemoveDiacritics(string s)
{
string normalizedString = null;
StringBuilder stringBuilder = new StringBuilder();
normalizedString = s.Normalize(NormalizationForm.FormD);
int i = 0;
char c = '\0';
for (i = 0; i <= normalizedString.Length - 1; i++)
{
c = normalizedString[i];
if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
{
stringBuilder.Append(c);
}
}
return stringBuilder.ToString().ToLower();
}
我想你已经回答了你自己的问题。“如果我设置field=”无论如何“;永远不会抛出错误!!”但我需要将字段放入.csv文件中!我不知道那是什么意思。常识应该规定给变量一些初始值,即使该值是空字符串或null。以后您可以在该变量中添加其他值。如果我将此行“field=fields[0];”替换为“field=”ANYTHING“;”。错误不会发生。但如果我不这么做,错误就来了occurs@Robert哈维。“您可以在以后将其他值放入该变量。”如果我尝试从文件中放入该值,在大多数情况下,AccessViolationException会在不同字段上随机发生。我想您已经回答了自己的问题。“如果我设置field=”无论如何“;永远不会抛出错误!!”但我需要将字段放入.csv文件中!我不知道那是什么意思。常识应该规定给变量一些初始值,即使该值是空字符串或null。以后您可以在该变量中添加其他值。如果我将此行“field=fields[0];”替换为“field=”ANYTHING“;”。错误不会发生。但如果我不这么做,错误就来了occurs@Robert哈维。“以后您可以在该变量中添加其他值。”如果我尝试从文件中添加该值,在大多数情况下,AccessViolationException会随机出现在不同的字段中。您知道如何操作吗?由于我在Cstring和C++之间的转换过程中丢失了所有的数据,解释如何编写正确的C++代码需要一本书,它不适合这样的答案。我试图在回答的最后一段提到这一点。请尝试利用我所记录的内容,如果这个C++函数没有用于任何其他事情,除了p援引,那么使用COTASKMeMalAcLoad(),这样pPoNKE封送器就很高兴了。但是我必须继续使用A2OLE或A2W吗?这是我发现的唯一一种将CString投射到LPWSTR的方法。我也不知道
private void processImport()
{
string[] fields;
string field ;
string temp = "";
byte[] tempByte;
TextFieldParser parser = new TextFieldParser(textbox_csv.Text, System.Text.Encoding.UTF8);
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(";");
while (!parser.EndOfData)
{
fields = parser.ReadFields();
field = fields[0];
temp = RemoveDiacritics(field).ToUpper();
//this line is very important. It seems to change the Encoding of my string to Unicode.
temp = temp.Normalize(NormalizationForm.FormC);
field = myVbDll.MyWrappedFunction(temp, false);
}
parser.Close();
}
//Transforms the culture of a letter to its equivalent representation in the 0-127 ascii table, such as the letter 'é' is substituted by an 'e'
public string RemoveDiacritics(string s)
{
string normalizedString = null;
StringBuilder stringBuilder = new StringBuilder();
normalizedString = s.Normalize(NormalizationForm.FormD);
int i = 0;
char c = '\0';
for (i = 0; i <= normalizedString.Length - 1; i++)
{
c = normalizedString[i];
if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
{
stringBuilder.Append(c);
}
}
return stringBuilder.ToString().ToLower();
}
Public Class myVbDll
<DllImport("Wrapper.dll", CharSet:=CharSet.Unicode)> Public Shared Function MyWrappedFunction (ByVal nom As String, ByVal opt As Boolean) As String
End Function
End Class
typedef void (*MYFUNCTION)(CString&, CString&, BYTE);
MYFUNCTION Myfunction;
LPWSTR _stdcall MyWrappedFunction(LPWSTR ValInput, BYTE opt)
{
HINSTANCE gLibtestDLL=NULL;
CString S_ValInput(ValInput);
CString S_resultat;
gLibtestDLL = AfxLoadLibrary(TEXT(".\\test.dll"));
if(gLibtestDLL == NULL)
{
MessageBox(NULL, TEXT("unable to load test.DLL"), TEXT("Error"),MB_OK | MB_ICONINFORMATION);
return NULL;
}
Myfunction = (MYFUNCTION)GetProcAddress(gLibtestDLL, "Myfunction");
if (Myfunction == NULL)
{
MessageBox(NULL, TEXT("Can't find Myfunction."), TEXT("Error"),MB_OK | MB_ICONINFORMATION);
return NULL;
}
//******************************************************************
S_resultat.Format("%64c", ' ');
Myfunction(S_ValInput , S_resultat , opt); //Run MFC function
S_resultat.TrimRight();
S_resultat.ReleaseBuffer();
char* tmp = (char*) CoTaskMemAlloc((S_resultat.GetLength()*2)+1);
memset(tmp,0,sizeof(tmp));
strcpy_s(tmp, (S_resultat.GetLength()+1), S_resultat.GetBuffer(S_resultat.GetLength()));
S_resultat.ReleaseBuffer();
wchar_t wtext[1024];
memset(wtext,0,sizeof(wtext));
mbstowcs(wtext, tmp, strlen(tmp)+1);//Plus \0
LPWSTR resultat = wtext;
AfxFreeLibrary(gLibtestDLL);
return resultat;
}