Сбой COM-взаимодействия в режиме выпуска
У меня есть консольное приложение, которое выполняет поиск Windows с помощью ComImport. Хотя это нормально работает в режиме отладки... консольное приложение падает в режиме выпуска. В чем может быть проблема?
[ComImport]
[Guid("9DAA54E8-CD95-4107-8E7F-BA3F24732D95")]
[ClassInterface(ClassInterfaceType.None)]
[TypeLibType(TypeLibTypeFlags.FCanCreate)]
public class WordBreaker : IWordBreaker
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern bool Init([In] bool query, [In] uint maxTokenSize);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void BreakText([In, MarshalAs(UnmanagedType.LPStruct)] TEXT_SOURCE textSource,
[In] IWordSink wordSink, [In] IPhraseSink phraseSink);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void ComposePhrase([In, MarshalAs(UnmanagedType.LPWStr)] string noun, [In] uint nounLen,
[In, MarshalAs(UnmanagedType.LPWStr)] string modifier, [In] uint modifierLen,
[In] uint attachmentType, [Out] out IntPtr phrase, [In, Out] ref uint phraseLen);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern IntPtr GetLicenseToUse();
}
Код не работает в режиме выпуска при доступе к функции WordBreaker.BreakText.
Он используется в моем коде, как показано ниже
if (!string.IsNullOrWhiteSpace(text))
try
{
IWordBreaker breaker = new WordBreaker();
bool reqLicense = breaker.Init(query, 256);
if (reqLicense)
{
IntPtr lic = breaker.GetLicenseToUse();
string licText = Marshal.PtrToStringUni(lic);
}
TEXT_SOURCE source = new TEXT_SOURCE();
source.fillTextBuffer = FillTextBuffer;
source.buffer = text;
source.cur = 0;
source.end = (uint)(text.Length);
breaker.BreakText(source, new WordSink(result), null);
}
catch (Exception ex)
{
Console.Out.WriteLine(ex.ToString());
//log4net.LogManager.GetLogger(typeof(WindowsIntegration)).Error("BreakText", ex);
}
var resultWithoutNoise = NoiseWord.Remove(result);
return resultWithoutNoise;
}
Авария происходит в breaker.BreakText
именно BreakText
Функция вызывается много раз (от 500 до 7000 раз), прежде чем приложение вылетает.
Аварийный сбой говорит следующее об информации об исключенииThe thread tried to read from or write to a virtual address for which it does not have the appropriate access.
примечание: я не использую никаких потоков в моем коде.
3 ответа
Коду нужен как минимум один поток, на который ссылается ошибка. Что касается типа сбоя, это, по сути, нарушение доступа, либо из-за нулевого указателя / ссылки на объект (в собственном коде), либо из-за переполнения буфера. Проверьте какие значения. строка. длины и т. д., что вы передаете в точке, где это не удается.
Это похоже на случай, когда сборщик мусора перемещает текст в другое место, поэтому адрес, записанный в source.buffer, больше не действителен. Вы не включили источник, который объявляет TEXT_SOURCE, поэтому я не могу комментировать это. Но объявление BreakText не является правильным. MarshalAs(UnmanagedType.LPStruct) не должен использоваться там. UnmanagedType.LPStruct поддерживается только для одного конкретного случая: обработка типа значения System.Guid как неуправляемого GUID с дополнительным уровнем косвенности. См. http://blogs.msdn.com/b/adam_nathan/archive/2003/04/23/56635.aspx и Как маршалировать структуру как указатель на структуру?,
Если вы не можете воспроизвести проблему и она делает это только в релизе, я настоятельно рекомендую вам добавить ведение журнала, чтобы сузить проблему.
Когда вы сузите проблему, я отредактирую ваш пост выше, чтобы включить более подробную информацию о сбое.