ScintillaNET crashing on AppendText

Topics: Developer Forum, User Forum
Mar 25, 2014 at 10:35 PM
Edited Mar 25, 2014 at 10:43 PM
ScintillaNET control used in a C# Windows Forms application seems to corrupt memory after using AppendText, and crashes the program.

Sometimes this happens with not a very large amount of text, like 7000-8000 characters only.

I can get it to happen consistently with a for loop - eventually it will crash no matter what.

This happens when using the "plus equals" operator or AppendText.

Both of them cause the same crash.

Basically I am trying to use ScintillaNET as a fast replacement for a sluggish RichTextBox in an application that constantly appends text to the control. Seems to work great EXCEPT for this crash bug. It crashes without even very much text. It tends to crash sooner when I append more text in one block at one time. Any fix for this or a workaround?
Coordinator
Mar 26, 2014 at 12:26 AM
Can you provide a sample application? My guess is that it has nothing to do with the amount of text you're appending. Usually this has to do with encoding issues. Scintilla doesn't natively use UTF-16, however, .NET does. For us to get your text into the Scintilla control we need to convert it. It's possible we've made a mistake in how we're doing that.

These kinds of problems are usually more apparent when you have a character that requires two or more bytes to encode. As a test, see if you have any problems by appending a string of 'a' characters i.e. "aaaaaaa" in a loop and see if you still get a crash.

P.S. Don't use the += operator when simply appending text. That would cause the entire contents of the control to get copied to a temporary byte array, then to a new string, then to a second string with your appended text, then to another temporary byte array, and then back into the control. i.e. it's a very expensive way to add text.

P.P.S If by chance you're doing this append operation on a background thread... you can't. Make sure you're only touching the Scintilla control on the main UI thread.

Thanks,
Jacob
Mar 26, 2014 at 11:44 AM
Edited Mar 26, 2014 at 1:17 PM
Sure, as a simple example, this will crash it:
for (int i = 0; i < 1400; i++)
                scintilla1.AppendText("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n");
Granted that's quite a few characters, probably around 90-100k, but it's still not that many. And that's the simplest example.

I would think it would just not add any more text if it experienced some sort of buffer overflow, so it seems like that's not what's happening? Is there anything I could do to test this, for example convert to another character set before appending to the control?

It'll do it with 7000-8000 characters in some cases, if I use different characters.

As another example, if I just paste this over and over again:
:: Settings:
:: AutoLog Interval: 0 seconds
:: History Length: 200 commands
:: Scroll Buffer Length: 3000 lines
:: Echo is On
:: Clear Input is On
:: Highlight Input is Off
:: Aliases: 0
:: Actions: 0
::
:: Type #? for a list of ZenMu commands.
::
:: Click Reconnect to connect to:
:: kier.com 8500

It'll crash a lot sooner.

This is all done from the main UI thread.
Coordinator
Mar 27, 2014 at 1:05 AM
Ya, I got nothin'. I can't reproduce this no matter how many ways I try. I can change your 'for' loop to 10400 iterations instead of just 1400. I can paste your text snippet until it gets ridiculous. Still nothing.

I'm starting to think maybe there is an issue with your program. Are you listening to any Scintilla events like UpdateUI, SelectionChange, TextChange, etc... I'm wondering if an error in one of those--which could be triggered by a lot of appended text--could be your problem.

If you are listening to any of those events you might try to temporarily remove them and see if you still get the same problem.


Jacob
Mar 27, 2014 at 11:52 AM
Well let me share the configuration of the system too, maybe something there...

So I'm running ScintillaNET v2.6, just recently downloaded the other day.

The application is a C# Windows Forms app running on Win7 64 bit, without admin privileges. I'm using Visual Studio 2010 with .NET Framework 4.

I'm not listening to any of the Scintilla events, so that shouldn't be an issue...

For some background on the app, formerly I was using a RichTextBox as my main display window for inputted text. The problem is that the text can get very long, and contains lots of color codes that need to be translated into text color. I got this all working great, but then I noticed the performance dropped linearly with text length... which doesn't work for this app at all. After trying a million ways to manipulate the underlying RTF of the RichTextBox to improve performance with no result, I came across this ScintillaNET control. So this is a drop-in replacement for a RichTextBox.

However, just to get everything working, I kept it super simple to start and set it up to only write text to the Scintilla control using AppendText. I literally do no other operations to the control yet (although I will need event listeners at some point).

Also here's the error text (FatalExecutionEngineError), just in case it's helpful:
The runtime has encountered a fatal error. The address of the error was at 0x5c28d379, on thread 0x26dc. The error code is 0xc0000005. This error may be a bug in the CLR or in the unsafe or non-verifiable portions of user code. Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack.
I have a lot of initialization code before I'm calling the for loop with AppendText - I'll remove that bit by bit just to see if anything is related. If you can get it to work with a 10400 loop, it must be something in here...
Mar 27, 2014 at 12:07 PM
Edited Mar 27, 2014 at 2:47 PM
I found the problem!

So I have a loop to set up fonts in the ScintillaNET control. I call this before calling the AppendText loop.

This is the function:
public static void UpdateScintillaFonts(Scintilla box, Font newFont)
        {
            for (int i = 0; i < 16; i++)
            {
                box.Styles[i].Font = newFont;
            }
        }
If (and only if!) I pass the "DefaultFont" of the main form to this function, I get that crash when I call lots of AppendTexts. This happens even if I change the "i < 16" to be "i < 2" and even if I allocate new memory for the font:
box.Styles[i].Font = new Font(newFont, FontStyle.Regular);
It does work correctly if I only set the Styles[0] font, or if I use any other font other than the DefaultFont from the Windows form.

Also, it appears that once I try to set multiple Styles to the DefaultFont, something gets "screwed up." The crash occurs even if I reset all those Style[x] fonts to a different font and then call the 1400 iterations of AppendText. It's almost like some sort of memory corruption is occurring when the DefaultFont is passed in to multiple styles the first time. Who knows, maybe something is wrong with the DefaultFont itself and it has nothing to do with the Scintilla control.

Strange! In any case I don't have to use that font, I can just create a new one and use that instead. Seems to work fine as long as I don't touch the DefaultFont from the Windows form. So I think I'm good.
Coordinator
Mar 27, 2014 at 4:08 PM
Ya that's interesting. The exception you're getting suggests memory corruption. My recollection is that system fonts (DefaultFont) are not meant to be disposed. It's possible that Scintilla is disposing of the default font, ScintillaNET is disposing of the default font, or something else is and the result is the font is no longer at address 0x5c28d379.

Or it could be something else entirely... but I'm glad you figured it out. :)

Jacob
Mar 27, 2014 at 5:00 PM
Edited Mar 27, 2014 at 5:06 PM
Could be... I'm noticing that if I change fonts to the Styles more than once or twice I seem to get the crash again, even if I'm not using DefaultFont anymore. It seems like the Scintilla control can handle setting the Style fonts once, but then changing them to anything different seems to cause a crash down the road.

I thought it was only DefaultFont at first, but that's because I was trying to reset the Styles to use the same font as they had previously. I'm assuming when a Style font is set, it probably checks its current font, and if they match, ignores the change.
Mar 27, 2014 at 7:18 PM
Edited Mar 27, 2014 at 8:43 PM
Wrote a solution here but it turns out it doesn't work, so I removed it... I tried doing a Dispose on the Style font before setting a new one but that doesn't seem to help.

So it looks like changing Style fonts on the fly is bugged.