summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormark@chromium.org <mark@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-24 23:32:13 +0000
committermark@chromium.org <mark@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-24 23:32:13 +0000
commit1bc2de46d9bdcab02caa8a4623c08472d71aa8d7 (patch)
treee360a34935f0862ee63384d11254538a1ebb4d24
parent476de223832b5c9e5ed739e08abadac74dabee25 (diff)
downloadchromium_src-1bc2de46d9bdcab02caa8a4623c08472d71aa8d7.zip
chromium_src-1bc2de46d9bdcab02caa8a4623c08472d71aa8d7.tar.gz
chromium_src-1bc2de46d9bdcab02caa8a4623c08472d71aa8d7.tar.bz2
Explicitly instantiate the string16 backer exactly once, avoiding problems in
shared library builds and an Apple ld bug Review URL: http://codereview.chromium.org/49023 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@12406 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--base/string16.cc2
-rw-r--r--base/string16.h41
2 files changed, 43 insertions, 0 deletions
diff --git a/base/string16.cc b/base/string16.cc
index a47a147..ca45fba 100644
--- a/base/string16.cc
+++ b/base/string16.cc
@@ -67,6 +67,8 @@ char16* c16memset(char16* s, char16 c, size_t n) {
} // namespace base
+template class std::basic_string<char16, base::string16_char_traits>;
+
std::ostream& operator<<(std::ostream& out, const string16& str) {
return out << UTF16ToUTF8(str);
}
diff --git a/base/string16.h b/base/string16.h
index 11f79e3..df9e039 100644
--- a/base/string16.h
+++ b/base/string16.h
@@ -122,6 +122,47 @@ struct string16_char_traits {
} // namespace base
+// The string class will be explicitly instantiated only once, in string16.cc.
+//
+// std::basic_string<> in GNU libstdc++ contains a static data member,
+// _S_empty_rep_storage, to represent empty strings. When an operation such
+// as assignment or destruction is performed on a string, causing its existing
+// data member to be invalidated, it must not be freed if this static data
+// member is being used. Otherwise, it counts as an attempt to free static
+// (and not allocated) data, which is a memory error.
+//
+// Generally, due to C++ template magic, _S_empty_rep_storage will be marked
+// as a coalesced symbol, meaning that the linker will combine multiple
+// instances into a single one when generating output.
+//
+// If a string class is used by multiple shared libraries, a problem occurs.
+// Each library will get its own copy of _S_empty_rep_storage. When strings
+// are passed across a library boundary for alteration or destruction, memory
+// errors will result. GNU libstdc++ contains a configuration option,
+// --enable-fully-dynamic-string (_GLIBCXX_FULLY_DYNAMIC_STRING), which
+// disables the static data member optimization, but it's a good optimization
+// and non-STL code is generally at the mercy of the system's STL
+// configuration. Fully-dynamic strings are not the default for GNU libstdc++
+// libstdc++ itself or for the libstdc++ installations on the systems we care
+// about, such as Mac OS X and relevant flavors of Linux.
+//
+// See also http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24196 .
+//
+// To avoid problems, string classes need to be explicitly instantiated only
+// once, in exactly one library. All other string users see it via an "extern"
+// declaration. This is precisely how GNU libstdc++ handles
+// std::basic_string<char> (string) and std::basic_string<wchar_t> (wstring).
+//
+// This also works around a Mac OS X linker bug in ld64-85.2.1 (Xcode 3.1.2),
+// in which the linker does not fully coalesce symbols when dead code
+// stripping is enabled. This bug causes the memory errors described above
+// to occur even when a std::basic_string<> does not cross shared library
+// boundaries, such as in statically-linked executables.
+//
+// TODO(mark): File this bug with Apple and update this note with a bug number.
+
+extern template class std::basic_string<char16, base::string16_char_traits>;
+
typedef std::basic_string<char16, base::string16_char_traits> string16;
extern std::ostream& operator<<(std::ostream& out, const string16& str);