簡體   English   中英

C ++ .NET包裝器:嘗試讀取或寫入受保護的內存。 這通常表明其他內存已損壞

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM