2011-06-29 60 views
3

我有一個控制檯應用程序使用ComImport調用Windows搜索。 雖然這在調試模式下正常工作...控制檯應用程序在發佈模式下崩潰。 可能是什麼問題?COM互操作失敗發佈模式

[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. 注意:我沒有在我的代碼中使用任何線程。

+2

它究竟是如何崩潰,究竟是哪個代碼? – sharptooth

+0

@sharptooth:添加了deatails – Mulki

+0

@Mulki你有沒有什麼運氣調試這個? –

回答

0

如果您無法重現該問題,並且它僅在發佈版中提供,我強烈建議您添加日誌記錄以縮小您的問題範圍。

當你縮小了你的問題範圍時,我會編輯你的帖子以包含更多關於崩潰的詳細信息。

+0

已經完成loggig..i確切地知道它在哪裏崩潰...檢查上面的細節..只是增加 – Mulki

+0

您可能希望記錄您傳遞到BreakText的所有內容,看看您是否看到任何可疑內容。 FillTextBuffer,文本,文本,長度,結果等 –

+0

文本,text.length和結果都很好.... FillTextBuffer是一個常量= 0x80041700 – Mulki

1

該代碼需要至少一個線程,這是錯誤引用。 至於崩潰的類型,它本質上是一個訪問衝突,可以是一個空指針/對象引用(在本機代碼中)或緩衝區溢出。 檢查什麼值。串。長度等,你在傳遞失敗的時候傳入。

+0

沒有線程參與..它運行在單個線程中。相同的代碼在調試模式下工作正常。在代碼中沒有針對調試或發佈模式的特殊處理..如何在調試模式下工作而不是在發佈模式下工作。 – Mulki

+0

調試模式(至少對於本地調試)通常會在變量/內存周圍添加額外的填充以允許/捕獲像這樣的問題。發佈不。 – Deanna

+0

你能指點我解釋這個的任何文檔嗎? – Mulki

1

這看起來像垃圾收集器正在將文本移動到另一個位置,以便記錄在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.aspxHow do I marshal a structure as a pointer to a structure?