[英]Attempted to read or write protected memory. This is often an indication that other memory is corrupt. in C++ Dll
[英]C++ .NET Wrapper: Attempted to read or write protected memory. This is often an indication that other memory is corrupt
我有一個用於未管理的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”循環中。 有時它會在開始時拋出,有時會在中間拋出,有時什么也不會拋出。
工作原理:我的程序需要MFC dll。 我的程序中引用了wrapper.dll(c ++)和myVbDll.dll(vb.net)。 我還添加了MFC dll作為內容,因為它不是有效的COM組件。 因此,它是這樣工作的:
myProgramm.exe-> myVbDll.dll-> wrapper.dll-> myMFC.dll-> myMFCfunction
INFO:如果我設置field = "WHATSOEVER";
就在調用MyWrappedFunction之前,從未拋出錯誤!
更新:經過幾次更改后,問題仍然存在。 我看着這次將unicode字符串轉換為Ansi。 可能會發現一些問題……原因是當您在上面的字符串中編寫文本時,它可以工作,但是當使用ToString函數時,它不起作用。
有人能說出為什么會發生這種情況嗎?
我的程序在C#中的一部分(使用TextFieldParser從.csv文件讀取5000行以獲取字段):
string[] fields;
string field ;
string temp = "";
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 = field.ToUpper();
field = myVbDll.MyWrappedFunction(ref temp, false);
}
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
MFC包裝程序的一部分,由VB.net Dll調用(肯定不是MFC dll出錯):
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.LockBuffer();
S_resultat.Format("%64c", ' ');
Myfunction(S_ValInput , S_resultat , opt);
S_resultat.ReleaseBuffer();
S_resultat.LockBuffer();
S_resultat.TrimRight();
S_resultat.ReleaseBuffer();
// CString To UNICODE
USES_CONVERSION;
S_resultat.LockBuffer();
LPWSTR C_tmp= A2OLE(S_resultat.GetBuffer(S_resultat.GetLength()));
S_resultat.ReleaseBuffer();
AfxFreeLibrary(gLibtestDLL);
LPWSTR C_resultat=C_tmp;
//******************************************************************
return C_resultat;
}
LPWSTR C_tmp= A2OLE(S_resultat.GetBuffer(S_resultat.GetLength()));
這是C ++代碼中的一個非常嚴重的錯誤。 您正在返回局部變量的地址。 由A2OLE()創建的緩沖區。 這會在C ++代碼中調用未定義的行為 。 當您從C ++代碼中調用此函數時,這往往會意外地起作用,您會感到有些奇怪,不會再有另一個函數調用會覆蓋該局部變量曾經使用的堆棧地址。 當您調用該函數時,這些幾率變為零,而調用pinvoke編組函數調用會使堆棧地址消失。 如果那本身並不會導致崩潰,則pinvoke編組將確保在嘗試使用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();
}
VB.net Dll的一部分,由我的c#程序調用:
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
C ++包裝的一部分,由VB.net Dll調用:
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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.