8

我有一台 OS X 10.6 Mac 作为我的开发机器。我编写的程序在开发机器上运行良好。但是,当我尝试在 OS X 10.5(不确定是否相关)测试机器上运行它时,它在启动时崩溃。

这是我得到的错误:

Process:         MyApp[25908]
Path:            /Applications/MyApp.app/Contents/MacOS/MyApp
Identifier:      MyApp
Version:         ??? (???)
Code Type:       X86 (Native)
Parent Process:  launchd [109]

Interval Since Last Report:          17392106 sec
Crashes Since Last Report:           735
Per-App Interval Since Last Report:  0 sec
Per-App Crashes Since Last Report:   8

Date/Time:       2010-08-14 07:50:09.768 -0700
OS Version:      Mac OS X 10.5.8 (9L31a)
Report Version:  6
Anonymous UUID:  1BF30470-ACF2-46C7-B6D5-4514380965C8

Exception Type:  EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000002, 0x0000000000000000
Crashed Thread:  0

Dyld Error Message:
  Symbol not found: __ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_i
  Referenced from: /Applications/MyApp.app/Contents/MacOS/MyApp
  Expected in: /usr/lib/libstdc++.6.dylib

所以看起来它正在崩溃,因为它正在加载动态库 libstdc++.6 的不兼容版本。这种东西普通吗?在 Google 上搜索并没有真正发现许多其他存在此问题的程序。我应该在编译中做什么来防止这种情况发生?我是否需要以某种方式将 libstdc++ 包含在我的应用程序包中?

4

3 回答 3

9

此问题的解决方案是将以下代码添加到您的源文件之一:

// Workarounds for symbols that are missing from Leopard stdlibc++.dylib.
_GLIBCXX_BEGIN_NAMESPACE(std)
// From ostream_insert.h
template ostream& __ostream_insert(ostream&, const char*, streamsize);

#ifdef _GLIBCXX_USE_WCHAR_T
    template wostream& __ostream_insert(wostream&, const wchar_t*, streamsize);
#endif

// From ostream.tcc
template ostream& ostream::_M_insert(long);
template ostream& ostream::_M_insert(unsigned long);
template ostream& ostream::_M_insert(bool);
#ifdef _GLIBCXX_USE_LONG_LONG
    template ostream& ostream::_M_insert(long long);
    template ostream& ostream::_M_insert(unsigned long long);
#endif
template ostream& ostream::_M_insert(double);
template ostream& ostream::_M_insert(long double);
template ostream& ostream::_M_insert(const void*);

#ifdef _GLIBCXX_USE_WCHAR_T
    template wostream& wostream::_M_insert(long);
    template wostream& wostream::_M_insert(unsigned long);
    template wostream& wostream::_M_insert(bool);
    #ifdef _GLIBCXX_USE_LONG_LONG
        template wostream& wostream::_M_insert(long long);
        template wostream& wostream::_M_insert(unsigned long long);
    #endif
    template wostream& wostream::_M_insert(double);
    template wostream& wostream::_M_insert(long double);
    template wostream& wostream::_M_insert(const void*);
#endif

// From istream.tcc
template istream& istream::_M_extract(unsigned short&);
template istream& istream::_M_extract(unsigned int&);  
template istream& istream::_M_extract(long&);
template istream& istream::_M_extract(unsigned long&);
template istream& istream::_M_extract(bool&);
#ifdef _GLIBCXX_USE_LONG_LONG
    template istream& istream::_M_extract(long long&);
    template istream& istream::_M_extract(unsigned long long&);
#endif
template istream& istream::_M_extract(float&);
template istream& istream::_M_extract(double&);
template istream& istream::_M_extract(long double&);
template istream& istream::_M_extract(void*&);

#ifdef _GLIBCXX_USE_WCHAR_T
    template wistream& wistream::_M_extract(unsigned short&);
    template wistream& wistream::_M_extract(unsigned int&);  
    template wistream& wistream::_M_extract(long&);
    template wistream& wistream::_M_extract(unsigned long&);
    template wistream& wistream::_M_extract(bool&);
    #ifdef _GLIBCXX_USE_LONG_LONG
        template wistream& wistream::_M_extract(long long&);
        template wistream& wistream::_M_extract(unsigned long long&);
    #endif
    template wistream& wistream::_M_extract(float&);
    template wistream& wistream::_M_extract(double&);
    template wistream& wistream::_M_extract(long double&);
    template wistream& wistream::_M_extract(void*&);
#endif

_GLIBCXX_END_NAMESPACE

根本问题是在 libstdc++ 标头中有几个模板被声明为 extern 模板,虽然它们的实例化由 libstdc++ 在 10.6+ 上提供,但它们不是由 libstdc++ 在 10.5 上提供的。结果,当您使用这些模板时,您最终会成功链接到 10.6 SDK 以获取 10.5 操作系统未提供的功能,因此 dyld 在启动时会报废。通过自己提供实例化,您可以确保您的代码将加载到 Snow Leopard 上。

或者,您可以

#define _GLIBCXX_EXTERN_TEMPLATE 0 

在您的前缀文件中,但这样做会导致模板代码膨胀。

于 2011-09-12T20:39:19.600 回答
2

我能想到的有几点:

  1. 您是否将其编译为“发布版本”?调试版本可能无法在编译它的机器以外的机器上运行。

  2. 你用的是哪个SDK?您在构建设置中指定了哪个最低操作系统版本?如果要在 10.5 上运行它,则需要使用 10.5 SDK 和/或将目标操作系统设置为 10.5。请参阅有关为多个操作系统版本构建的Apple 文档

  3. 目标机器是否DYLD_LIBRARY_PATH设置为非空?如果不仔细做,可能会混淆dyld

区分各种可能性的一种方法是在开发机器上运行您的应用程序,但使用一个单独的帐户,该帐户没有开发帐户的管理员权限;然后你可以测试它是否在 10.6 的盒子里运行。

于 2010-08-14T17:45:52.890 回答
0

我遇到了同样的问题(使用 GCC 4.2 构建使我的代码无法在 OS X 10.5 上执行,因为 libstdc++.6.dylib 中的 dyld 错误)。

Ben Artin 提出的解决方案有效。或者,您可以在添加任何头文件之前将定义 _GLIBCXX_EXTERN_TEMPLATE 设置为零(如果您使用的是预编译头文件,请确保使用定义集正确编译它们)。

于 2011-09-13T08:55:32.067 回答