3

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 information The 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.

Whimsical
  • 5,985
  • 1
  • 31
  • 39

3 Answers3

1

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?.

Community
  • 1
  • 1
Eric MSFT
  • 3,246
  • 1
  • 18
  • 28
1

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.

Deanna
  • 23,876
  • 7
  • 71
  • 156
  • There are no threads involved..its running in a single thread. The same code works fine in debug mode. There is no special handling for debug or release mode in the code..how can this work on the exact same input set in debug mode but not in release mode. – Whimsical Jun 30 '11 at 13:09
  • Debug mode (at least for native debugging) normally puts extra padding around variables/memory to allow/catch problems like this. release doesn't. – Deanna Jul 01 '11 at 08:56
0

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.

Cole W
  • 15,123
  • 6
  • 51
  • 85
  • already done loggig..i Know exactly where its crashing...check details above..just added – Whimsical Jun 29 '11 at 11:43
  • You may want to log everything you are passing into BreakText to see if you see anything fishy. FillTextBuffer, text, text.Length, result etc. – Cole W Jun 29 '11 at 13:30
  • Text, text.length and result are fine.... FillTextBuffer is a constant = 0x80041700 – Whimsical Jun 30 '11 at 13:06