8

This happens only in x64 version

An unhandled exception of type 'System.ArithmeticException' occurred in WindowsBase.dll Additional information: Overflow or underflow in the arithmetic operation.

Crashing at line

gridcontainer.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);

If I remove the line it crashes as soon as it starts updating layout with no source available

00000101  test        ecx,ecx 
00000103  je          0000000000000124 
00000105  lea         rdx,[rbp+18h] 
00000109  mov         rcx,qword ptr [rbp+70h] 
0000010d  call        0000000000216100 
00000112  cmp         byte ptr [rdi],0 

Do you know how to prevent it?

Exception:

    System.ArithmeticException: Overflow or underflow in the arithmetic operation.
   at System.Windows.UIElement.RoundLayoutSize(Size size, Double dpiScaleX, Double dpiScaleY)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.VirtualizingStackPanel.MeasureChild(IItemContainerGenerator& generator, IContainItemStorage& itemStorageProvider, IContainItemStorage& parentItemStorageProvider, Object& parentItem, Boolean& hasUniformOrAverageContainerSizeBeenSet, Double& computedUniformOrAverageContainerSize, Boolean& computedAreContainersUniformlySized, IList& items, Object& item, IList& children, Int32& childIndex, Boolean& visualOrderChanged, Boolean& isHorizontal, Size& childConstraint, Rect& viewport, VirtualizationCacheLength& cacheSize, VirtualizationCacheLengthUnit& cacheUnit, Boolean& foundFirstItemInViewport, Double& firstItemInViewportOffset, Size& stackPixelSize, Size& stackPixelSizeInViewport, Size& stackPixelSizeInCacheBeforeViewport, Size& stackPixelSizeInCacheAfterViewport, Size& stackLogicalSize, Size& stackLogicalSizeInViewport, Size& stackLogicalSizeInCacheBeforeViewport, Size& stackLogicalSizeInCacheAfterViewport, Boolean& mustDisableVirtualization, Boolean isBeforeFirstItem, Boolean isAfterFirstItem, Boolean isAfterLastItem, Boolean skipActualMeasure, Boolean skipGeneration, Boolean& hasBringIntoViewContainerBeenMeasured, Boolean& hasVirtualizingChildren)
   at System.Windows.Controls.VirtualizingStackPanel.MeasureOverrideImpl(Size constraint, Nullable`1& lastPageSafeOffset, List`1& previouslyMeasuredOffsets, Boolean remeasure)
   at System.Windows.Controls.VirtualizingStackPanel.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint)
   at System.Windows.Controls.ItemsPresenter.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint)
   at System.Windows.Controls.ScrollContentPresenter.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV)
   at System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV, Boolean& hasDesiredSizeUChanged)
   at System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV)
   at System.Windows.Controls.Grid.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.ScrollViewer.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.Border.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.Control.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.DockPanel.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV)
   at System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV, Boolean& hasDesiredSizeUChanged)
   at System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV)
   at System.Windows.Controls.Grid.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.ContextLayoutManager.UpdateLayout()
   at System.Windows.ContextLayoutManager.UpdateLayoutCallback(Object arg)
   at System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
   at System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget)
   at System.Windows.Media.MediaContext.RenderMessageHandler(Object resizedCompositionTarget)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
Daniel
  • 1,064
  • 2
  • 13
  • 30
  • Do you have extremely large or small UI elements? If you enable Break on Exceptions, can you see any of the parameters anywhere on that stack trace in the Locals window? – SLaks Aug 14 '14 at 16:17
  • 6
    Set a breakpoint on a line closest to the crash. When it hits, use Debug + Windows + Registers. Right-click and tick "Floating point". The CTRL register should be `027F`. Right-click and tick "SSE". The MXCSR register should be `00001F80`. If they don't have these values then you can get these exceptions. You'll need to find the external code that reprograms these registers, use this debug window to find it. Throw an exception intentionally and catch it to get the registers restored. – Hans Passant Aug 14 '14 at 16:23
  • @HansPassant `CTRL=1372` and `MXCSR=000019A0`. Calling before that `_controlfp(_MCW_EM, _EM_INVALID);` fixes it for x86 but not for x64. It is a shell context menu extension that changes FPU, but considering how many there are, I need to fix it. – Daniel Aug 14 '14 at 16:47
  • Just uninstall it, it can crash many programs beyond yours. – Hans Passant Aug 14 '14 at 16:59
  • @HansPassant I installed after report by one user to verify. Problem is that some users have that extension or some other shell extension that creates the same problem. Is there a way to reset it on x64? – Daniel Aug 14 '14 at 17:20
  • 2
    Then you of course need to recommend those users to uninstall it. Or contact the owner of that shell extension to get support, this is not your bug. Not mentioning in your question that you *knew* that the problem was caused by a shell extension is incredibly bad form btw, shame on you. – Hans Passant Aug 14 '14 at 17:31
  • @HansPassant Sorry for not mentioning. I consider that preventing these kind of user mistakes is also developer's responsibility; another invalid input from user. Recently I contacted support of a prg that is broken when text scaling is enabled, and their reply was "reset scaling to default". As I might need scaling, this user might need that extension. Thanks for showing me how to work with registers! – Daniel Aug 14 '14 at 21:07
  • @SLaks There are no very small or large UI elements. Too bad it does not output the name of the element where the measuring exception occurred. – Daniel Aug 14 '14 at 21:08
  • Not an expert here, but it could be caused by a division by zero or a number type being setted beind its limits, like an integer being setted higher than `int.MAX_VALUE`. – Ricardo Souza Aug 25 '14 at 15:26

2 Answers2

1

We occasionally receive such reports from our users. It seems the issue is related to floating point unit corruption, like described in this question. Unfortunately it is not clear how to handle such error inside framework calls.

UPD: I created following workaround based on presentation framework source code. Initialize workaround with single call: UIHelper.InitWPFArithmeticExceptionWorkaround()

public static class UIHelper
{
    [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern int _fpreset();

    private static DispatcherOperationCallback _oldUpdateLayoutCallback;
    private static object UpdateLayoutCallback(object arg)
    {
        try
        {
            _oldUpdateLayoutCallback(arg);
            return null;
        }
        catch (System.Xaml.XamlParseException ex)
        {
            if (!(ex.InnerException is ArithmeticException))
            {
                throw;
            }
        }
        // Try to update layout second time after floating point unit reset
        _fpreset();
        _oldUpdateLayoutCallback(arg);
        return null;
    }

    public static bool InitWPFArithmeticExceptionWorkaround()
    {
        try
        {
            // Call fpreset early just to handle case with missed "msvcrt.dll" 
            // in future Windows versions
            _fpreset();
            Assembly assembly = typeof(System.Windows.UIElement).Assembly;
            Type managerType = assembly.GetType("System.Windows.ContextLayoutManager");
            if (managerType != null)
            {
                FieldInfo field = managerType.GetField("_updateCallback", BindingFlags.Static | BindingFlags.NonPublic);
                if (field != null)
                {
                    _oldUpdateLayoutCallback = field.GetValue(null) as DispatcherOperationCallback;
                    if (_oldUpdateLayoutCallback != null)
                    {
                        field.SetValue(null, new DispatcherOperationCallback(UpdateLayoutCallback));
                        return true;
                    }
                }
            }
        }
        catch
        {
        }
        return false;
    }
}
Andrey
  • 722
  • 2
  • 8
  • 17
-1

It looks like you are trying to draw something very large or very small. For all computed values that relate to drawing or user controlled values, always set a minimal size and check them before you call draw/render/paint/invoke.

When using custom drawing make sure that you check your app when it is maximized and minimized

Another place where this can happen is when you have a data grid with too many columns (if the total width exceeds 65k pixels). I saw that happen on a data grid but I think you should ensure that all of your controls are not too large.

Avia
  • 1,829
  • 2
  • 14
  • 15