as the title already may tell, I am encountering an AccessViolationException as I'm trying to paint a Control in .NET using a BufferedGraphics
object. This happens after a while, ealier or later. Evaluating the object's address, I noticed that it kept increasing as the program went on.
I've already taken a few measures to preserve memory, which seemed to help a bit, but did not ultimately solve the problem. It seems that the problem occurs independently of whether I dispose of the graphics object before the end of the function.
private void checkMemory()
{
long mem = GC.GetTotalMemory(false);
//Console.WriteLine("Allocated memory: " + mem.ToString());
if (mem > criticalMemorySize)
{
Console.WriteLine("GC started");
GC.Collect(1, GCCollectionMode.Forced, true);
}
}
BufferedGraphics graphics;
protected override void OnPaint(PaintEventArgs e)
{
lock (e.Graphics)
{
base.OnPaint(e);
checkMemory();
if (e.ClipRectangle.Width * e.ClipRectangle.Height == 0)
return;
if (graphics == null || graphics.Graphics == null || graphics.Graphics.ClipBounds != e.ClipRectangle)
graphics = _bufferedGraphicsContext.Allocate(e.Graphics, e.ClipRectangle);
PaintBackground(graphics.Graphics);
PaintHeader(graphics.Graphics);
PaintBody(graphics.Graphics);
DrawGrid(graphics.Graphics);
//...
graphics.Render(e.Graphics);
graphics.Graphics.Dispose();
graphics.Dispose();
}
}
The exception occurs in this function when calling g.DrawString
:
private void PaintBody(Graphics g)
{
Font seriffont = Design.CreateSerifFont(fontSize);
Point mousePos = PointToClient(MousePosition);
int hfeed = headHeight + headLineWidth - 2; //Dunno
for (int y = 0; y < LineCount; y++)
{
int vfeed = 0;
for (int x = 0; x < ColumnCount; x++)
{
String s = "";
Rectangle area = new Rectangle(vfeed, hfeed, colwidth, cellHeight);
switch (_tableData[y][x])
{
case ExBool.DontCare:
s = "*";
break;
case ExBool.False:
s = "0";
break;
case ExBool.True:
s = "1";
break;
default:
s = " ";
break;
}
Color backColor = cellBackColor;
if (_activeHeaderColumn == x)
{
backColor = cellActiveColColor;
}
if (area.Contains(mousePos))
{
backColor = cellHoverColor;
}
if (area.Contains(mousePos) &&
((MouseButtons & MouseButtons.Left) == MouseButtons.Left))
{
backColor = cellActiveColor;
}
g.FillRectangle(new SolidBrush(backColor), area);
g.DrawString(s, seriffont, Brushes.Black, area,
new StringFormat() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
if (x != InputValues.Count() - 1)
{
vfeed += lineWidth + colwidth;
}
else
{
vfeed += typeSepLineWidth + colwidth;
}
}
hfeed += cellHeight + lineWidth;
}
}
And this is the exception I am getting:
System.AccessViolationException was unhandled
HResult = -2147467261
Message=Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben.Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist.
Source= System.Drawing
StackTrace:
bei System.Drawing.SafeNativeMethods.Gdip.GdipDrawString(HandleRef graphics, String textString, Int32 length, HandleRef font, GPRECTF& layoutRect, HandleRef stringFormat, HandleRef brush)
bei System.Drawing.Graphics.DrawString(String s, Font font, Brush brush, RectangleF layoutRectangle, StringFormat format)
bei KarnaughVeitch.Controls.TruthTableControl.PaintBody(Graphics g)
bei KarnaughVeitch.Controls.TruthTableControl.OnPaint(PaintEventArgs e)
bei KarnaughVeitch.Controls.TruthTableControl.TruthTableControl_MouseMove(Object sender, MouseEventArgs e)
bei System.Windows.Forms.Control.OnMouseMove(MouseEventArgs e)
bei System.Windows.Forms.Control.WmMouseMove(Message& m)
bei System.Windows.Forms.Control.WndProc(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
bei System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
bei System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
bei System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
bei System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
bei System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
bei System.Windows.Forms.Application.Run(Form mainForm)
bei KarnaughVeitch.Program.Main()
bei System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
bei System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
bei Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
bei System.Threading.ThreadHelper.ThreadStart_Context(Object state)
bei System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
bei System.Threading.ThreadHelper.ThreadStart()
InnerException:
Does anyone have an idea how to solve this? Thanks in advance!
Edit:
The Context variable is created globally like this:
BufferedGraphicsContext _bufferedGraphicsContext = new BufferedGraphicsContext()
This was recommended in the documentation for the case that you would frequently use BufferedGraphics
.
The functions are part of a custom Control that allows for the user to enter binary function inputs and outputs. Since I didn't know of any similar control, I just wrote one myself.
The above function is called everytime the Control needs to be repainted, e.g. if the user moves the mouse, clicks on something and so on, for all of these actions require a visual feedback.
Generally, it works as desired, except for the Exception which occurs after using the Control for quite a while...
Edit 2:
Since the exception occurs almost exclusively on DrawString
functions, would it be possible, that the NullReference (according to the HResult, if I am not mistaken) is not due to the drawing process itself, but rather due to one of the arguments or something?