我正在调试 OS X 上的一个问题,该问题仅在应用程序从扩展坞启动时发生。从命令行启动应用程序时不会发生这种情况。这两种情况有什么区别?我正在使用的代码是在第三方应用程序中加载的基于 c++ 的捆绑插件。在这两种情况下,我都使用 GDB 附加到进程,我能看到的唯一区别是从命令行运行时在进程中加载了几个额外的 dylib,并且我的库的基地址在两种情况。我尝试将链接更改为 -prebind 和/或 -bind_at_load 无济于事。
4 回答
一个重要的区别是初始工作目录在每种情况下都是不同的。应用程序永远不应该对工作目录做出任何假设,如果这样做的话,将会以有趣的方式中断。
从 Dock 图标启动的应用程序不会选择您正在使用的 shell 中设置的相同环境变量。如果您依赖于从环境中获取某些东西,您将需要寻找不同的方法。您将获得一些环境变量,例如 PATH、HOME、LOGNAME 等。但如果您正在寻找 HOSTTYPE、LANG、OSTYPE 等,它们将不会出现。
在这种情况下,我的问题是由加载共享库的顺序不同引起的。我们的应用程序使用的第三方库之一将扩展库加载到全局命名空间中。与同一库的不同版本存在符号冲突。扩展库加载到全局池中的顺序会根据应用程序是从文档启动还是从命令行启动而变化。
在类似的情况下,我从应用程序包运行时发生了崩溃。一种可能性是我们正在使用我们已经释放的内存。例如,在 or 之后使用指针或类的free()
字段delete
。
看起来应用程序包与不同的free/delete
实现动态链接,该实现将已释放的内存归零/修改。
使用其他平台/编译器(例如 Linux/gcc、Windows/Visual Studio、macOS/clang 从命令行)可能不会出现这种错误,并且仅在从应用程序包执行程序时出现(来自 Finder/dock 的 macOS/clang )。