Wednesday, December 7, 2011

Visual C++ 2010 std::istringstream crash in destructor

tl;dr: You have a /vd2 switch in your project settings that you don't know about. Check your property sheets, gtkmm in particular has it in the additional options. [edit 11-dec-2011: but read the update at the bottom, it's not that simple]

I have a Visual C++ 2008 project that uses gtkmm, sqlite and curl that I wanted to port 2010. Most of the times, upgrading a project to a newer version of Visual C++ works quite well, but I got a crash immediately after the first build on a destructor for a std::istringstream. std::ostringstream also crashes in the destructor. The error message is
Unhandled exception at 0xwherever (ntdll.dll) in program.exe: 0xC0000005:
Access violation reading location 0x00000004.
right in
virtual ~basic_istringstream()
  {  // destroy the object
  }
 with this stack trace (edited for sanity)
ntdll.dll!_NtRaiseException@12() + 0x12 bytes
ntdll.dll!_NtRaiseException@12() + 0x12 bytes
msvcr100d.dll!_free() + 0x10 bytes
program.exe!std::istringstream::~istringstream() Line 469 + 0x20
program.exe!std::istringstream::`vbase destructor'() + 0x2e bytes
I also saw
ntdll.dll!_NtRaiseException@12() + 0x12 bytes
ntdll.dll!_NtRaiseException@12() + 0x12 bytes
msvcr100d.dll!__unlock() + 0x16 bytes
and
ntdll.dll!_NtRaiseException@12()  + 0x12 bytes
ntdll.dll!_NtRaiseException@12()  + 0x12 bytes
msvcr100d.dll!__free_dbg()  + 0x68 bytes
msvcp100d.dll!std::_DebugHeapDelete<_RTL_CRITICAL_SECTION>()  + 0x15 bytes
The first thing I found was a bug report on Microsoft Connect that was about the /vd2 switch, which I'd never heard of before and therefore do not use in my projects. I dismissed it quickly and moved on to not finding anything else.

After multiple rebuilds, checking dll dependencies and generally not having much of a clue, I started looking at the exact command line for my project in the property pages, but still could not find anything useful.

I then started to look at the individual property sheets, starting with gtkmm, where I obviously found this little /vd2 switch in the additional options of the command line. Funnily enough, it looks like these additional options are not shown on the "all options" text box of the project itself. Removing the switch fixed the crash.

Now, fixing a crash is always nice, but finding the reason for the crash is better, so it can be avoided in the future.

This gtkmm bug report dated from November 2004 states that Visual Studio 2003 had a problem with using dynamic_cast in constructors. The fix on Visual Studio 2005 was to use the /vd2 flag. Moving on to 2010, /vd2 broke for unknown reasons, but this is not fixable without breaking binary compatibility, which is not happening until the next major release. I haven't tested whether the /vd2 flag is still necessary (two bug reports seem to indicate it still is, as no resolution has been posted), but preliminary tests seem to be okay.

Therefore, it looks like the /vd flag was extended as a bugfix for 2005, but 2010 introduced a bug on the bugfix. Hopefully, the 2005 bug is gone or we'll need a bugfix for the bugfix. Who said programming wasn't fun?

There's not much internets on this, although there are two threads on gnome's mailing list and a bug report on googletest (where a guy closed it quite unceremoniously "as this is a compiler bug") that appear when searching specifically for "gtkmm" and "vd2".

[edit 11-dec-2011:

I just got linked in a stackoverflow question. I was wondering where that traffic came from.

My "preliminary tests" was successfully running a somewhat complex gtkmm application without /vd2. It was obviously not enough. This (adapted from the OP's code):
#include <cassert>
#include <sstream>

struct object
{
  virtual ~object() {}
};

struct base : virtual object
{
  base()
  {
    object* b = static_cast<object*>(this);
    base* d = dynamic_cast<base*>(b);
    
    assert(this == d);
  }
};

struct derived : base
{
  int i;
};

int main()
{
  derived d;
}

fails with Visual C++ 2010, but not with g++ 4.5.3. Adding /vd2 to the compiler settings fixes the problem, but then changing main() to

int main()
{
  derived d;
  std::istringstream iss;
}

again fails in istringstream::~istringstream().

What happens in base::base() is legal as per 12.7/5 in C++03 and 12.7/6 in C++11:
When a dynamic_cast is used in a constructor [..] if the operand of the dynamic_cast refers to the object under construction or destruction, this object is considered to be a most derived object that has the type of the constructor or destructor’s class.
Therefore, as long as T refers to a direct or indirect base type of U, U::U() can dynamic_cast this to T and back.

As far as I can tell, there is no way to fix this so that both dynamic_cast in a constructor and stringstreams can work. I don't even know the extent of the problem with /vd2 in Visual C++ 2010 (why only stringstreams?). Documentation on the /vd2 switch for 2010 says that
/vd supports incorrect behavior in an early version of Visual C++, and is no longer needed.
 but that is not what I and others see.]

[edit 28-jun-2012:

Although the dynamic_cast still fails miserably without /vd2, stringstreams now behave correctly on Visual C++ 2012 RC]

Saturday, July 9, 2011

Internet explorer 9 always in quirks mode for local files

While working on canui, I was trying to check some examples with internet explorer 9. These examples were on my local apache server. After getting some errors about the canvas object, I opened up the developer tools (in the sprocket icon) and noticed the "document mode" was in "quirks mode."

I first realized that I hadn't included a doctype declaration. The HTML5 doctype is simply

<!DOCTYPE html>

However, even with the doctype, the page was still staying in quirks mode. Pages like the fish test were working fine. When I noticed that my examples were working fine from sourceforge, my google searches changed from "always in quirks mode" to "quirks mode localhost" and I quickly found a KB article about compatibility view.

After feeling like an idiot for a few seconds about not finding the "compatibility view settings" item in the sprocket menu, I stopped looking at the images and started reading the actual text and understood that the Tools menu is not the sprocket menu. Pressing alt brings it up. I blame the lack of coffee at that time.

In the compatibility view settings, there is a checkbox "Display intranet sites in compatibility view" that is checked by default. Unchecking it fixes problem.

Therefore, make sure:
  1. the html page starts with <!DOCTYPE html> but without anything before it, including a BOM mark;
  2. the compatility view settings (in the Tools menu) for local files is unchecked;
  3. you're not forcing any specific document mode in the developers tools;
  4. you're not using any kind of X-UA-Compatible meta tags;
  5. the windows group policy isn't forcing compatibility mode.

Monday, July 4, 2011

Canvas user interface

I am currently developing a user interface library for the HTML5 canvas element. I named it canui and it is hosted on sourceforge.



Wednesday, May 25, 2011

Inheritance and virtual functions in javascript

Javascript has no built-in facilities for inheritance or virtual functions. Inheritance lets you define common functionality in a base class that can be extended or modified in a derived class. A virtual function is a function that can be redefined in a derived class and will correctly be called on an instance of that class. Although crude virtual functions can be done by assigning a different function to the object, calling the base class implementation becomes harder.

I've come up (although it might already be popular, I'm not entirely sure) with a scheme to create hierarchies with virtual function tables. Although it requires more typing and some discipline, it emulates inheritance and virtual functions correctly.

A class that is meant to be derived from is defined as a regular function, taking the derived class's this object as a parameter.

function inherit_base(self)
{
  self.member = 1;

  self.base__frob = function()
  {
    alert("frobbing base");
  }

  self.frob = self.base__frob;
}

function derived()
{
  inherit_base(this);
 
  this.frob = function()
  {
    this.base__frob();
    alert("frobbing derived");
  }
}

var d = new derived();
d.frob();

The "virtual function table" is defined at the end of inherit_base. The derived class can call the base's implementation while adding functionality.

If the base class can either be derived from or instantiated (that is, it is not what's commonly called abstract),
then a base class can be defined and derived from inherit_base:

function base()
{
  inherit_base(this);
}

This requires discipline: functions in the base class need to have a distinct name (here I use the base__ prefix) and be assigned to the "virtual" function's name afterwards. As with most languages, the base class implementation needs to be called manually from the derived class.

Wednesday, March 30, 2011

Code::Blocks, Visual C++ and precompiled headers

C::B supports precompiled headers that are created like gcc does: compile the header into a .gch and gcc will find it if it's in the same directory as the header. Visual C++'s precompiled headers require distinct flags for creating and using the precompiled header.

Because C::B doesn't support per-file configuration, giving different options to files is impossible, unless you use the "custom build" option in the properties.

So, here's how you can use precompiled headers with Visual C++ 2005/2008. I'm assuming the names pch.cpp and pch.h.
  1. Add pch.cpp and pch.h to the project.
  2. Go in the project's build options, "Compiler settings" tab, "Other options" section, and add:
    /Yupch.h /Fp$objects_output_dir\pch.obj
    Careful: if pch.cpp is not in the same directory as the project file, you'll need to specify it manually. I usually have the project file in / and my sources in /src. Therefore, I use:
    /Fp$objects_output_dir\src\pch.obj
    This is because C::B creates a directory structure in $objects_out_dir that's similar to the one for source files.
  3. Right-click on pch.cpp, select "Properties". 
    1. In the "Build" tab, uncheck "Link file" and move the priority slider to 0. This makes sure the pch is compiled first.
    2. In the "Advanced" tab, check "Use custom command to build this file" and enter:
      $compiler /nologo $options $includes /c $file /Ycpch.h
It is possible to avoid entering the path by hand in /Fp by simply using $objects_output_dir. While this works fine, it breaks C::B's build system, which expects to see the object file in the right directory. Your program will still compile and link fine, but it will always try to rebuild the pch, because it's not in the right place. It will also never clean it.

This also relies on cl.exe being able to choose between /Yu (set in the build options, included through $options in the custom command)  and /Yc (set in the custom command) when both are specified, which is the case while compiling pch.cpp. This seems to work fine on both 2005 and 2008.

[edit 31-mar-2011: Ugh, there's more problems than I thought with this. The above tricks the build system into thinking that pch.obj is a regular object file. This way, it is generated and cleaned correctly. However, it is not an object file, it is a precompiled header. That's why you need to uncheck "Link file".

I realized that a pch.obj was still being generated in the root directory. This is because /Fo is not specified in the custom command. That pch.obj is the real object file generated by pch.cpp.

I now understand that Visual C++ generates two files when compiling pch.cpp: a precompiled header (pch.pch) and an object file (pch.obj). The former is used in each subsequent file using /Yu and the latter is linked at the end. This allows adding definitions in pch.cpp.

The scheme above does not link with pch.cpp because its object file is the precompiled header.

There are two possibilities here:
  1. Getting rid of the pch.obj in the root directory: This would be fine if you didn't need to link with pch.cpp at all. I can't find any way to do this. cl.exe has no way of saying: use this file to generate a precompiled header, but no object file. The /Yc flag is meant to generate the precompiled header in addition to the regular object file.

    You can however add a post-build step "cmd /c del pch.obj" which will delete the stray pch.obj from disk. This is something of a hack, but it works.

  2. Generate both the precompiled header and object file correctly and link with the object file: This is the behavior of Visual C++. To do this, the precompiled header needs to use a different extension, such as .pch, so it doesn't clash with the object file:
    1. Change /Fp in the project build options to generate "pch.pch" instead of "pch.obj".
    2. Recheck "Link file" in pch.cpp's properties and add "/Fo$object" back to the custom command.

    This way, you'll end up with both pch.pch and pch.obj in the output directory and pch.obj will be linked correctly. This is the typical Visual C++ behavior. However, you now have a file pch.pch of which C::B knows nothing about, because it was generated behind its back with /Yc. Therefore, cleaning the project will not delete that file.
I can't find any way of emulating Visual C++'s behavior exactly: if you generate both files, one of them won't be cleaned. If you don't specify /Fo, you can't link with pch.cpp and you end up with an unused object file in the root directory.

I could probably make this work if C::B had a place to specify additional files to clean, but there's not.]

[edit 14-sep-2011: typos]

Monday, March 28, 2011

Code::Blocks and visual c++ 2010 help system

I've recently been trying to move from Visual C++ to Code::Blocks for several of my projects. One issue I've had was to integrate the Visual C++ help system with the help plugin.

I couldn't make this work with Visual C++ 9.0 because dexplorer.exe does not seem to allow forcing a single instance. Something like:

"C:\Program Files\Common Files\microsoft shared\Help 9\dexplore.exe" /helpcol ms-help://MS.VSCC.v90 /LaunchFKeywordTopic $(keyword)

works, but always opens in a new window. Visual Studio starts dexplore.exe with -Embedding, but it looks like it's sending windows message afterwards, not relying on instances.

However, I found H3Viewer, a dexplorer-like viewer for the Visual C++ 2010 documentation. Setting the command line to:

"C:\Program Files\Helpware\H3Viewer\h3viewer.exe" "http://127.0.0.1:47873/help/1-6992/ms.help?product=VS&productVersion=100&locale=en-us&method=search&query=$(keyword)&format=html&PageSize=200&PageNumber=1"

works nicely. Unchecking "Open F1 Topics in a New Tab" in H3Viewer will always reuse the current tab instead of opening a new one.

Monday, March 21, 2011

Implementation details

A program is composed of building blocks, or layers. Ideally, each layer should be independent and communicate in a way that changes in a deeper layer do not affect a higher layer, unless the public interface, the facade, is modified. This is the basis for encapsulation: do not expose what does not need to be exposed.

As an example, take a function get_page(const uri&) that queries a web server using HTTP and returns the content of the page as a string. Whether get_page() uses raw sockets, libcurl or Boost.Asio should not affect the calling code, since the facade is the same: give me a URI and I'll give you back a string.

There are many ways of isolating layers so that implementation details are hidden. Some allow only a relink, while others force a recompile, although without requiring modifications to the calling code. Some are easier on maintenance, but are more complex to implement.

As with most things in programming, there is always a compromise to be made between development time and maintenance time. Experience will make the extent of this compromise easier to define, based on the nature of the program, time constraints, skill and managerial issues. While ignoring encapsulation may be just fine for small, quick-and-dirty programs, it is not for larger codebases. Remember also that what started as a small program can easily get out of hands if its scope gets larger with time. I've been bitten more than once by the "bah, 'tis just a small debug thing, oh darn now it needs a boatload of features, oh crap it needs to be ported to Linux, oh god help me now it's got to run in production."

Never assume that your "small debug thing" will stay that way. Always program as well as your time constraints allow.

The following examples are taken from a real project that pretty much went through these "oh crap" steps. Although it needed some refactoring several times, using some kind of encapsulation from the start helped me reduce the time needed for modifications.

The final version of this program takes a list of (x, y) points from an external source (such as a CSV file) and displays them on an OpenGL context. It needs to support basic graphical operations such as zooming and panning, as well as data modifications such as rotating and translating the points. It has to run on both Windows and QNX.

The examples will concentrate on the OpenGL part, because it can demonstrate the different methods of encapsulation:
  • Windows supports OpenGL 1.1 out of the box, while QNX only supports OpenGL ES 1.0, a subset of OpenGL.
  • The creation of the OpenGL context and user interface elements is different on both platforms.
  • OpenGL ES is messy to use and benefits from some sort of wrapping.
Because not everybody may be acquainted with OpenGL or QNX, the examples will not require any special knowledge. This is not a tutorial on using OpenGL and therefore the code using it will not be complete.

Monday, March 7, 2011

On the matter of exceptions

There was a post recently on the visual c++ blog about exceptions in which some of the comments were interesting. It eventually ended up being about four things:
  • Exceptions vs. return values
  • Throwing objects vs. throwing fundamental types
  • Exception hierarchies vs. embedding values
  • Lack of a finally construct

Exceptions vs. return values: a database lookup

[update 9-mar-2010, thanks to G: The following is a simplified example of a database query to illustrate the different error handling strategies. A real program would have to handle many more different types of errors. However, I consider them variations on the same theme: logic errors, runtime errors and exceptional paths.

Additionally, programming is a job like others and therefore has constraints that usually have a higher priority, such as a delivering date or existing coding standards. However, paying attention to error handling will make it easier in the long term to maintain a codebase.]

A function get_item() searches a database for the item corresponding to a given id. It may encounter three problems:
  1. the backend finds the SQL statement to be malformed;
  2. the backend reports an error during the query (such as a broken connection); or
  3. the item is not found in the database.
 These three errors are on three different levels:
  1. this is a logic error that is preventable. It is a result of a programming error;
  2. this is a runtime error that is not preventable. It is a result of the environment in which the program is running being in an bad state;
  3. this is a runtime error that may or may not be preventable, depending on the context.
Error handling for these errors mostly depends on the application (especially the third one), although they happen frequently enough so that we can make some assumptions.