COM 互操作在发布模式下失败
我有一个控制台应用程序,它使用 ComImport 调用 Windows 搜索。 虽然这在调试模式下工作正常...但控制台应用程序在发布模式下崩溃。 可能是什么问题?
[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 次)。
故障转储显示以下有关异常信息的内容 线程尝试读取或写入它没有适当访问权限的虚拟地址。
注意:我的代码中没有使用任何线程。
I have a console app which makes a call to the windows search using a ComImport.
While this works fine in debug mode...the console application crashes in release mode.
What could be the problem?
[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();
}
The code fails in release mode while accessing WordBreaker.BreakText function.
It is being used in my code as shown below
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;
}
The crash occurs in breaker.BreakText
exactly
The BreakText
function is called many times (between 500 to 7000 times) before the app crashes.
The crashdump says the following about exception informationThe thread tried to read from or write to a virtual address for which it does not have the appropriate access.
note: I am not using any threads in my code.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
该代码至少需要一个线程,这就是错误所指的。
至于崩溃的类型,它本质上是访问冲突,要么是空指针/对象引用(在本机代码中)要么是缓冲区溢出。
检查什么值。细绳。长度等你在失败时传递的内容。
The code needs at least one thread which is what the error referred to.
As for the type of crash, it's essentially an access violation, either down to a null pointer/object reference (in native code) or a buffer over run.
Check what values. string. lengths, etc that you're passing in at the point it fails.
这看起来像是垃圾收集器将文本移动到另一个位置,因此 source.buffer 中记录的地址不再有效的情况。您尚未包含声明 TEXT_SOURCE 的源代码,因此我无法对此发表评论。但 BreakText 的声明不正确。不应在那里使用 MarshalAs(UnmanagedType.LPStruct)。仅支持一种特定情况:将 System.Guid 值类型视为具有额外间接级别的非托管 GUID。请参阅 http://blogs.msdn.com/b /adam_nathan/archive/2003/04/23/56635.aspx 和 如何将结构编组为指向一个结构?。
This looks like a case where the garbage collector is moving text to another location so the address recorded in source.buffer is no longer valid. You haven't included the source which declares TEXT_SOURCE so I can't comment on that. But the declaration of BreakText is not correct. MarshalAs(UnmanagedType.LPStruct) should not be used there. UnmanagedType.LPStruct is only supported for one specific case: treating a System.Guid value type as an unmanaged GUID with an extra level of indirection. See http://blogs.msdn.com/b/adam_nathan/archive/2003/04/23/56635.aspx and How do I marshal a structure as a pointer to a structure?.
如果您无法重现该问题并且仅在发布中出现,我强烈建议您添加日志记录来缩小问题范围。
当您缩小问题范围后,我会编辑您上面的帖子以包含有关崩溃的更详细信息。
If you're not able to reproduce the issue and it only does it in release I would highly suggest you add logging to narrow down your problem.
When you've narrowed down your problem I would edit your post above to include the more detailed information about the crash.