Thread safety for ID3v1 genres

Stephen F. Booth me at sbooth.org
Sun May 1 19:04:34 CEST 2011


I've been experiencing a crash that I can reproduce 100% of the time,
but I'm struggling on coming up with a good fix.

The crash is happening at line 257 of tstring.cpp:

const char *String::toCString(bool unicode) const
{
  delete [] d->CString;                                       // <==
CRASHES HERE
  std::string buffer = to8Bit(unicode);
  d->CString = new char[buffer.size() + 1];
  strcpy(d->CString, buffer.c_str());
  return d->CString;
}

The debugger says:

malloc: *** error for object 0x11a362100: pointer being freed was not allocated

After a bit of investigation, the string objects causing the crashes
are the ID3v1 genre strings, which are statically allocated and shared
across all ID3v1 tags.  If I process numerous MP3 files in parallel, I
will always see a crash when calling String::toCString on the ID3v1
tag's genre.  Obviously a double-free is occurring when two threads
are almost simultaneously following the same code path.

I am able to fix the problem by applying the following patch to id3v1genres.cpp:

diff --git a/taglib/mpeg/id3v1/id3v1genres.cpp
b/taglib/mpeg/id3v1/id3v1genres.cpp
index 7893c72..a977d41 100644
--- a/taglib/mpeg/id3v1/id3v1genres.cpp
+++ b/taglib/mpeg/id3v1/id3v1genres.cpp
@@ -31,7 +31,7 @@ namespace TagLib {
   namespace ID3v1 {

     static const int genresSize = 148;
-    static const String genres[] = {
+    static const char * genres[] = {
       "Blues",
       "Classic Rock",
       "Country",


Obviously this just forces a new string to be returned every time,
eliminating the shared nature of the genre strings  It isn't optimal,
because the memory footprint will increase, but at least it doesn't
crash.

Is there a better solution that I've missed?

Stephen


More information about the taglib-devel mailing list