【问题标题】:OS X program runs on dev machine, crashing horribly on othersOS X 程序在开发机器上运行,在其他机器上严重崩溃
【发布时间】:2010-08-14 15:46:11
【问题描述】:

我有一台 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++ 包含在我的应用程序包中?

【问题讨论】:

    标签: macos libstdc++


    【解决方案1】:

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

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

    你也可以

    #define _GLIBCXX_EXTERN_TEMPLATE 0 
    

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

    【讨论】:

    • 请注意,您需要包含<iostream> 才能使上述代码正常工作。
    【解决方案2】:

    我能想到几点:

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

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

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

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

    【讨论】:

    • 关于您的观点 1:如果调试版本适用于兼容的架构(例如,您没有尝试在 PowerPC 机器上运行 Intel 代码)并且不使用 ZeroLink(我不这样做) think 甚至可以在最新的 Xcode 上使用),那么调试版本应该可以工作。
    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-04
      • 1970-01-01
      • 2012-12-13
      • 1970-01-01
      相关资源
      最近更新 更多