Microsoft Epic Fail – Eine Odyssee

Manchmal nervt Programmieren einfach. Da hat man folgende Zeile in C++ (bääääh):

PathOption test = mQ1Settings->WorldDir;

Versucht man diese mit Visual C++ 2010 zu kompilieren, stürtzt der Compiler ab. WTF?

Ok, kann ja mal passieren. Also danach gegoogelt. Zu dem Problem gibt es auch schon einen Bug-Report bei Microsoft. Allerdings meint der Verantwortliche dazu:

I can confirm that this is a bug in our compiler. This crash is unfortunate, but … blablabla …, we believe that this is not critical to fix in the next release.

Ein Compiler-Fehler ist “not critical”???

Nach diesem Statement folgt dann noch:

We will keep this bug in our database and will reconsider it for future releases.

Aja. Deshalb hat der Bug-Report auch den Status “Geschlossenes als nicht lösbar”. Klingt natürlich total danach, dass man sich damit später noch mal befasst.

Na gut. Zum Glück gibt es ja die Möglichkeit, seinen eigenen Senf zu dem Bug-Report abzugeben. Dafür muss man sich zwar registrieren, aber einen Account bei Microsoft’s Bug-Tracker könnte man ja evtl. häufiger gebrauchen

registrieren.png

Also schnell auf “Registrieren” geklickt, irgendwelchen AGBs zugestimmt, und dann das:

registrieren-fehler.png

WTF? Das ganze noch zwei Mal probiert, mit dem gleichen Ergebnis.

Schon sichtlich genervt, gebe ich der Sache noch eine Chance. Zum Glück kann man ja Microsoft “hierüber einen Fehlerbericht” senden. Also klicke ich auf den Link, mit der Erwartung, dass Microsoft jetzt über diesen Fehler benachrichtigt wurde. Aber Pustekuchen!

msdn-forum.png

Ich lande in einem MSDN-Forum (mit dem viel-sagendenden Namen “MSDN, TechNet, and Expression Profile and Recognition System Discussions”).

Jetzt reicht’s mir. Wie oft will mich Microsoft denn noch auf eine andere Seite weiterleiten?? Ich wette, ich kann mich auch im MSDN-Forum nicht registrieren (hab ich allerdings nicht probiert). Dann darf ich am Ende einen Bug-Report (Forum) über einen Bug-Report (Microsoft’s Bug-Tracker) über einen Bug-Report (C++ Compiler) schreiben? Nein Danke!

Und dabei wollte ich doch einfach nur programmieren. Danke, Microsoft!

Update (22.6.2011): Das Problem besteht immer noch. Und ich habe inzwischen das Forum ausprobiert; wie erwartet tritt der Fehler hier auch auf, d.h. ich kann nicht mal einen Fehlerbericht im Forum schreiben. Das ist echt ne schwache Leistung, Microsoft!

WPF crashes on exit

So, I’m working on my WPF application and everything runs fine, but when I close it, I get this error message (together with this doesn’t-say-me-anything stacktrace):

[System.ComponentModel.Win32Exception]	{"Invalid window handle"}
  WindowsBase.dll!MS.Win32.HwndWrapper.DestroyWindow(object args) + 0x11a bytes	
  WindowsBase.dll!MS.Win32.HwndWrapper.Dispose(bool disposing, bool isHwndBeingDestroyed) + 0x8c bytes	
  WindowsBase.dll!MS.Win32.HwndWrapper.Dispose() + 0x14 bytes	
  PresentationCore.dll!System.Windows.Interop.HwndSource.Dispose(bool disposing) + 0x1f6 bytes	
  PresentationCore.dll!System.Windows.Interop.HwndSource.WeakEventDispatcherShutdown.OnShutdownFinished(object sender, System.EventArgs e) + 0x33 bytes	
  WindowsBase.dll!System.Windows.Threading.Dispatcher.ShutdownImplInSecurityContext(object state) + 0x49 bytes	
  mscorlib.dll!System.Threading.ExecutionContext.runTryCode(object userData) + 0x51 bytes	
  mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x6a bytes	
  mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool ignoreSyncCtx) + 0x7e bytes	
  mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x2c bytes	
  WindowsBase.dll!System.Windows.Threading.Dispatcher.ShutdownImpl() + 0x72 bytes	
  WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame) + 0xe1 bytes	
  WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame) + 0x49 bytes	
  WindowsBase.dll!System.Windows.Threading.Dispatcher.Run() + 0x4c bytes	
  PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore) + 0x17 bytes	
  PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window) + 0x6f bytes	
  PresentationFramework.dll!System.Windows.Application.Run(System.Windows.Window window) + 0x26 bytes	
  PresentationFramework.dll!System.Windows.Application.Run() + 0x1b bytes	
  GuideDock.exe!GuideDock.App.Main() + 0x94 bytes
  mscoreei.dll!__CorExeMain@0()  + 0x38 bytes	
  mscoree.dll!748c7f16() 	
  [Frames below may be incorrect and/or missing, no symbols loaded for mscoree.dll]	
  mscoree.dll!748c4de3() 	
  kernel32.dll!@BaseThreadInitThunk@12()  + 0x12 bytes	
  ntdll.dll!___RtlUserThreadStart@8()  + 0x27 bytes	
  ntdll.dll!__RtlUserThreadStart@8()  + 0x1b bytes

This problem seemed to appear only randomly until I figured it out today. The problem can be reproduce by this XAML/C# code (together with a WPF window):

1
2
3
4
5
6
7
8
9
10
11
12
13
public partial class MainWindow : Window {
  public MainWindow() {
    InitializeComponent();
 
    this.m_touchCanvas.MouseLeave += (s, e) => CrashAppOnClose();
  }
 
  private void CrashAppOnClose() {
    Window wnd = Window.GetWindow(this.m_touchCanvas);
    // This line throws a Win32Exception with "Ivalid window handle".
    wnd.PointToScreen(new Point());
  }
}

Now, when the user closes the window (without using the mouse; eg. with Alt+F4) while the mouse is still in the window, the call to wnd.PointToScreen() (line 11) results in the Win32Exception above. Unfortunately, the doesn’t seem to be any way to check whether this exception will be thrown – I already tried Window.IsLoaded as suggested here with no luck.

What’s more annoying is that the call to PointToScreen() does not appear in the stacktrace. I can’t even imaging how this is possible. That’s why it took me ages to figure this one out.

Btw: I’d like to send a bug report to Microsoft but they haven’t got my account working in three months.

Download the example project

Updates:

  • The problem only arises on 64-bit Windows system. A correct exception is thrown on 32-bit systems.
  • On 64-bit systems the Win32Exception can’t be caught in a try ... catch block. Both PointToScreen() and the point where the exception is thrown are on the same thread.
  • I’ve managed to create a bug report for this problem.

Solution/Workaround:
Given the 32-bit error message – which reads “This Visual is not connected to a PresentationSource.” – I found a way to circumvent this problem. You need to use PresentationSource.FromVisual like this:

private void CrashAppOnClose() {
  Window wnd = Window.GetWindow(this.m_touchCanvas);
  if (PresentationSource.FromVisual(wnd) != null) {
    wnd.PointToScreen(new Point());
  }
}

Hunting DLL loading errors

Today I tried the software I’ve been writing on another computer – and it immediately crashed. I got this error message:

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly ‘TrackerInterface-Mixed-Full.dll’ or one of its dependencies. The specified module could not be found.

Here, it tells me that my DLL “TrackerInterface-Mixed-Full.dll” could not be loaded. The first thing I thought was that the application couldn’t locate this DLL – because of the FileNotFoundException. Unfortunately this wasn’t the problem.

So I figured “or one of its dependencies” was the real problem. However, the error message doesn’t tell you what dependency (DLL) is actually missing – even when debugging.

So, I did some searching and found the Assembly Binding Log Viewer (or “Fusion Log Viewer”) which comes with Visual Studio. Unfortunately it didn’t do what I needed. It seems that this is actually more for .NET assemblies rather than native DLLs. (You need to run it with Adminstrator rights; otherwise it won’t work. Just in case you’ll ever need it.)

After some more searching I found a tool called Dependency Walker. And that’s exactly what did the trick. So I opened “TrackerInterface-Mixed-Full.dll” with it and got the following result:

Dependency Walker output with missing DLLs

Here you have my “TrackerInterface-Mixed-Full.dll” at the top of the tree and its dependencies listed below it. For one, you can see immediately that the file “QTCORED4.DLL” is missing. But you can also see that one dependency (“MAPPARSERD1.DLL”) is missing some dependencies as well. (Fortunately, Dependency Walker automatically expands all dependencies that again have missing dependencies.)

I hope this helps in case you’re running into this problem yourself.

Note: The part “The specified module could not be found.” of the error message indicates some missing DLLs. There can be other reasons for getting a “Could not load file or assembly ‘Assembly.dll’ or one of its dependencies.” which then have other texts after this one.

Note 2: This only seems to happen when using native DLLs from .NET applications/assemblies.

C++ and virtual methods (for C# or Java programmers)

Last friday I stumbled over a seroius shortcomming of C++ (compared to C# or Java) I’d like to share here with you. It’s about virtual methods called from a class constructor.

The C# Example

Let me start with an example. Here’s some C# code that simply calls a virtual method (named test()) from the class’ constructor:

class TestBaseClass {
  public TestBaseClass() {
    Console.Write("From base class: ");
    test();
  }

  protected virtual void test() {
    Console.WriteLine("in base class");
  }
}

Creating an instance of this class results in nothing special:

From base class: in base class

Now lets create a sub class of TestBaseClass and override the virtual method:

class TestSubClass : TestBaseClass {
  public TestSubClass() {
    Console.Write("From sub class: ");
    test();
  }

  protected override void test() {
    Console.WriteLine("in sub class");
  }
}

Now, creating an instance of TestSubClass will print this:

From base class: in sub class
From sub class: in sub class

This means that the sub class’ implementation of test() was executed (and not TestBaseClass‘ implementation) – just as expected.

Note: In Java all methods are automatically virtual. In contrast to C# or C++ you can’t create “non-virtual” methods in Java.

The C++ Problem

And exactly here is the problem in C++. Let’s create a C++ version of the two classes above (compiled with Visual C++).

Header file (TestClass.h):

#pragma once

class TestBaseClass {
public:
  TestBaseClass();

protected:
  virtual void test();
};


class TestSubClass : public TestBaseClass {
public:
  TestSubClass();

protected:
  virtual void test();
};

Source file (TestClass.cpp):

#include "TestClass.h"
#include <stdio.h>

TestBaseClass::TestBaseClass() {
  printf("From base class: ");
  test();
}

void TestBaseClass::test() {
  printf("in base class\n");
}


TestSubClass::TestSubClass() : TestBaseClass() {
  printf("From sub class: ");
  test();
}

void TestSubClass::test() {
  printf("in sub class\n");
}

Now, creating an instance of TestSubClass results in the following output:

From base class: in base class
From sub class: in sub class

Note how the base class’ implementation of test() is used in the base class constructor while the sub class’ implementation of test() is used in the sub class constructor.

The problem here (in constrast to C# or Java) is that the sub class constructor hasn’t been executed yet and therefore the “redirection” from TestBaseClass::test() to TestSubClass::test() hasn’t been established yet.

Rule: There is no way to call a sub class’ implementation of a virtual function in the base class constructor!

The problem becomes even more severe with pure virtual (which is abstract in C# and Java) methods. These methods don’t even have an implementation in the base class and therefore can’t be executed at all.

For your interest: A C++/CLI class will behave like a C# class (and not like a C++ class).

Example Visual Studio Solution

I’ve created a solution (for Visual Studio 2010) containing the source code above. In addition to a C# and a C++ project, I’ve also added a C++/CLI project. You can download it here:

VirtualMethodTest.zip