c # — Обнаружено переполнение буфера

У меня есть один вопрос, когда я использую C # DllImport C ++ dll, я использую Visual Studio 2010 & проверил «Включить отладку неуправляемого кода», при запуске всегда показывать сообщение «Обнаружено переполнение буфера! … Обнаружено переполнение буфера, которое повредило внутреннее состояние программы. Программа не может безопасно продолжить выполнение и теперь должна быть прекращена» «.

Эта dll предоставляется сторонними поставщиками, и они говорят, что запуск этой dll не является ошибкой, как я могу это исправить?

Моя M ++ функция DLL,

int  avc_to_avi_convert(char* chPath_avc, char* chPath_avi, int pPrivate, PROGRESS_CALLBACK progress_callback);

void avc_to_avi_close(int* pFd_avi);

typedef void (*PROGRESS_CALLBACK)(int iPercent, int pPrivate);

И я использую его в моем C # dllimport, как это:

public delegate void PROGRESS_CALLBACK(int _iPercent, int _pPrivate);

[DllImportAttribute(@"..\xxx.dll", EntryPoint = "avc_to_avi_convert", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]

public static extern unsafe int avc_to_avi_convert([MarshalAs(UnmanagedType.LPStr)] StringBuilder _inputAVC, [MarshalAs(UnmanagedType.LPStr)] StringBuilder _ouputAVI, int pPrivate, PROGRESS_CALLBACK _pg);

[DllImportAttribute(@"..\xxx.dll", EntryPoint = "avc_to_avi_close", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]

public static extern unsafe void avc_to_avi_close(int pFd_avi);

private void button1_Click(object sender, EventArgs e)
{
int i = 0;
StringBuilder inputFile = new StringBuilder(Application.StartupPath + @"\avc\abc.avc");//(@"C:\avc\abc.avc");
StringBuilder outputFile = new StringBuilder(Application.StartupPath + @"\avi\abc.avi");//(@"C:\avi\abc.avi");

if (avc_to_avi_convert(
inputFile,
outputFile,
1,
progress_func) > 0) {

}
}

public void progress_func(int iProgress, int pPrivate)
{
if (iProgress == 100)
{
//success
}
else if (iProgress == -1)
{
//convert error
}
else if (iProgress == -2)
{
//Not enough disk space
}
else
{
//update progress
}
}

Я изменил свой код на,

[DllImportAttribute(@"..\xxx.dll", EntryPoint = "avc_to_avi_convert", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)]

public static extern unsafe int avc_to_avi_convert([MarshalAs(UnmanagedType.BStr)] String _inputAVC, [MarshalAs(UnmanagedType.BStr)] String _ouputAVI, int pPrivate, PROGRESS_CALLBACK _pg);

[DllImportAttribute(@"..\xxx.dll", EntryPoint = "avc_to_avi_close", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)]

public static extern void avc_to_avi_close(ref int avi);

И запустил его, и я все еще получаю ту же ошибку.

1

Решение

1.) Вы уверены в соглашении о вызовах? Пытаться CallingConvention.StdCall, Прочитай это:

http://blogs.msdn.com/b/adam_nathan/archive/2003/05/21/56690.aspx

2.) Попробуйте другие значения для CharSet атрибут и использование String вместо StringBuilder для аргументов пути. Это хорошая ссылка:

http://msdn.microsoft.com/en-us/library/s9ts558h.aspx

3.) Кроме того, avc_to_avi_close метод должен выглядеть так:

[DllImportAttribute("xxx.dll", EntryPoint="avc_to_avi_close")]
public static extern void avc_to_avi_close(ref int avi);

4.) Другие вещи, которые вы хотите попробовать:

  • Используйте необычные комбинации CharSet а также MarshalAs, Например, вы знаете по ссылке выше, что Unicode следует использовать с LPWStr а также Ansi с LPStr но вы можете, конечно, попробовать другие комбинации.
  • Ваши внешние методы не должны быть отмечены unsafe,

Если вы исчерпали все другие варианты, почему бы вам не попробовать написать программу на C ++, аналогичную вашему C # -коду:

  • В случае сбоя вы доказали, что ошибка в библиотеке.
  • Если это не приводит к сбою, вы знаете, что ошибка заключается в использовании вами PInovke, и вы можете просмотреть все 12+ комбинаций из моего ответа одну за другой.
2

Другие решения

Вы передаете делегат p / invoke, а затем позволяете сборщику мусора освободить его. Это вызывает сбой, потому что, когда объект делегата завершен, батут, настроенный для разрешения вызовов из нативного кода, освобождается. Затем нативный код вызывает указатель на висячую функцию.

Сборщик мусора совершенно не знает о каких-либо объектах, используемых внутри нативного кода. Вы ДОЛЖНЫ поддерживать ссылку на делегата в течение всего разговора. Попробуйте добавить переменную делегата (не используйте неявное преобразование, которое создает временную переменную), а затем используйте GCHandle сохранить делегат живым, пока его использует нативный код.

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector