Search code examples
c#character-encodingpinvokedllimport

Aplication crashes when calling function from dll for character-set conversion


funcion on C

TCHAR* __stdcall W1251ToUtf8(CHAR* str)//функция пребразования строки из Windows-1251 в Unicode
{
    int wsize = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
    TCHAR* result = new TCHAR[wsize*sizeof(TCHAR)]; 
    MultiByteToWideChar(CP_UTF8, 0, str, -1, result, wsize);
    return result;
}

function declaration in c# project

[DllImport("D://EncodingStringData.dll", EntryPoint = "W1251ToUtf8")]
        static extern string W1251ToUtf8(string str);

function call

string TextForEncoding = ReadFromFile();
string OutText = W1251ToUtf8(TextForEncoding);

first time app crash without any reason, then im add try catch

try
            { 
                string TextForEncoding = ReadFromFile();
                string OutText = W1251ToUtf8(TextForEncoding);
            }
            catch (Win32Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.ToString());
            }  

and i catch accessviolationexception, now crashing againg without reason.

So anyone know what i need to do?


Solution

  • A few problems:

    • You pass 1251 text but ask it to be treated as UTF8. So the API function call likely fails. You don't check return value for failure.
    • Your input is 8 bit text, your output if 16 bit text, but your pinvoke assumes 8 bit for both.
    • A return value type of string leads to the returned pointer being passed CoTaskMemFree for deallocation.

    The exit code is STATUS_HEAP_CORRUPTION which suggests the final bullet is the immediate problem. Fix that by returning IntPtr and convert to text with Marshal.PtrToStringUni. And also export a deallocator. Or allocate off a shared heap. Or return a COM BStr. Indeed use any of the correct ways to return a string.

    Having fixed that problem you'll need to fix the others too.

    Quite why you won't use System.Text.Encoding is beyond me.