Archives

Creative Commons License
This blog is licensed under a Creative Commons License.

A C++ gotcha on Snow Leopard

| 3 Comments | No TrackBacks

I’ve seen this issue mentioned in some random and hard to reach places on the Net, so I thought I’d re-express it here for those who find Google sending them this way.

On Snow Leopard, Apple decided to build g++ and the standard C++ library with “fully dynamic strings” enabled. What this means for you relates to the empty string.

When fully dynamic strings are off (as was true in Leopard), there exists a single global variable representing the empty string. This variable lives in the data segment of libstdc++, and so it does not exist on the heap. Whenever a string is deconstructed, the standard library would check whether that string’s address matches matches the empty string’s: if so, it does nothing; if not, it calls free.

With fully dynamic strings on, there is no global empty string. All strings are on the heap, and once their reference count goes to zero, they get deallocated. Where this creates a problem is if you mix and match code. If a library that does have fully dynamic strings enabled (aka the standard library) receives an empty string from code which does not have it enabled (aka, the app you just built), it will try to free it and your application will crash.

Here’s a reproducible case for this issue using Boost:

#include <string>
#include <sstream>
#include <boost/variant.hpp>

int main()
{
  std::ostringstream buf;
  boost::variant<bool, std::string> data;
  data = buf.str();
  data = false;
  return 0;
}

In this case – which really happened to me – I created an empty string by calling ostringstream::str(). Since I don’t have fully dynamic string on, its address is in data space, not on the heap. I pass this string to boost::variant, which makes a copy of that address. Later, when the variant is reassigned false, it calls ~basic_string to deconstruct the string. Since my standard library is compiled with fully dynamic strings, the destructor for basic_string doesn’t recognize that its the “special” empty string, so it tries to free it.

The solution to this problem is three-fold:

  1. You must be using the g++ that comes with Xcode, or if you build your own (say, via MacPorts), you must configure it using --enable-fully-dynamic-string. I’ve already submitted a patch to this effect to the MacPorts crew.

  2. All libraries must be compiled with -D_GLIBCXX_FULLY_DYNAMIC_STRING.

  3. Your own code must be compiled with -D_GLIBCXX_FULLY_DYNAMIC_STRING.

You’ll know if this issue is biting you by looking at a stack trace in gdb. You’ll see a crash somewhere inside basic_string’s _M_destroy (which calls free). Move up the trace a bit and check whether the string it’s trying to free is 0 bytes long.

To recap: what’s happened is that an empty string constructed by code without fully dynamic strings got deallocated by code that was. That is, most likely you, or a library you built, handed an empty std::string to the system library.

No TrackBacks

TrackBack URL: http://www.newartisans.com/mt/mt-tb.cgi/2558

3 Comments

Thanks for posting this, although I confess I didn’t come across it until after I had spent many hours chasing the problem…

For my own system I’m fixing the problem by patching /usr/include/c++/4.2.1/x86_64-apple-darwin10/bits/c++config.h, to ensure that _GLIBCXX_FULLY_DYNAMIC_STRING is always set.

One thing that still confuses me about this bug is the fact that sometimes you dont see it. For example, my test case was even simpler than yours and the failure was caused simply by linking to a boost library: http://article.gmane.org/gmane.comp.lib.boost.user/53178

I’m struggling to come up with a better reason than “linker randomness” to explain this behaviour.

According to me, Apple has implemented something called blocks, which can be used to create both closures and anonymous functions. Both of these are something that C and C++ programmers could really use - the Standard Template Library would be massively improved by these new types of objects.

Something like this is slated for the next release of C++.

About this Entry

This page contains a single entry by John Wiegley published on October 30, 2009 4:35 AM.

Branch policies with Git was the previous entry in this blog.

A word on Haskell Monads and C++ is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.

Recent Comments

  • Curt Sampson: That there’s “no state” in Haskell is quite wrong; in read more
  • rv: Hi. I wanted to drop you a quick note to read more
  • John Wiegley: It’s here: http://ftp.newartisans.com/pub/python/modpython_gateway.py read more
  • Leon: The file “modpython_gateway.py” Is no longer available in the downloads read more
  • Kathy: Well, the article is really the sweetest on this laudable read more
  • mr.design: Hi John, I just started to read your GFTBU, it’s read more
  • yoman: “Barfin”? “Slurping”? “Slime” “Hunchentoot” ??? What in the T.F. world read more
  • John Wiegley: Something like this is slated for the next release of read more
  • womens health: According to me, Apple has implemented something called blocks, which read more
  • Bjorn Tipling: Why would you add instructions for installing an editor when read more
Powered by Movable Type 4.261