Fra*_*une 9 c++ macos gnu shared-libraries new-operator
多年来,我们一直在各种平台(Linux,Windows,Mac OS X,32位和64位)上构建大型开源软件,没有任何问题.然而,最近Mac OS X版本(64位)停止正常工作并开始随机崩溃.它或多或少与我们的构建机器上从10.7到10.8.2的Mac OS X更新一致(但编译器工具链没有改变,它仍然是llvm-gcc 4.2.1).
我们的应用程序由几个动态(共享)库和许多使用它们的可执行文件组成.由于各种原因,其中一个共享库会覆盖new和delete运算符.在Mac OS X(和Linux)上,默认情况下会导出所有符号,包括我们的重载new和delete运算符.Mac OS X上的崩溃似乎与一些内存子系统(不是我们的)分配的内存相关,然后通过我们自己的(并且不兼容的)delete实现释放.
最安静的解决方案似乎是阻止重载的操作员对共享库的用户可见.这可以通过两种方式实现:使用__attribute__((visibility("hidden")))或使用-unexported_symbols_list链接器命令行选项标记运算符以防止导出某些符号.遗憾的是,第一个解决方案不起作用:gcc发出警告,说操作符已被声明为不同(in <new>),因此属性将被忽略.根据我在不同地方的阅读,第二种解决方案似乎是解决这个问题的正确方法.但由于某种原因,我们无法使其发挥作用.
当链接共享库时,我们将-Wl,-unexported_symbols_list unexported_symbols_list.txt选项传递给g ++,而g ++又应该传递给ld.该unexported_symbols_list.txt文件包含以下符号列表:
__ZdaPv
__ZdaPvRKSt9nothrow_t
__ZdlPv
__ZdlPvRKSt9nothrow_t
__ZdlPvS_
__Znam
__ZnamRKSt9nothrow_t
__Znwm
__ZnwmPv
__ZnwmRKSt9nothrow_t
Run Code Online (Sandbox Code Playgroud)
这是所有的变化new和delete我们覆盖,并希望被隐藏.我们通过nm libappleseed.dylib使用将符号名称解开来找到这些符号c++filt.
这是CMake生成的命令行链接libappeseed.dylib:
/usr/bin/g++ -g -Werror -dynamiclib -Wl,-headerpad_max_install_names -framework Cocoa -lcurl -Werror -Wl,-unexported_symbols_list -Wl,unexported_symbols_list.txt -o ../mac-gcc4/appleseed/libappleseed.dylib [...]
Run Code Online (Sandbox Code Playgroud)
不幸的是,尽管我们付出了很多努力,但似乎仍然存在符号(如nm所示).
知道我们做错了什么吗?我们可以尝试另一种方法吗?
更新2012年12月19日:
Apple的技术说明中详细介绍了我们的问题和所谓的解决方案:http://developer.apple.com/library/mac/#technotes/tn2185/_index.html("覆盖新/删除"部分).
指向相关源代码的指针:
operator new和operator delete覆盖:allocator.cppnm构建libappleseed.dylib -fvisibility=hidden并运行后的输出片段strip -x libappleseed.dylib:
...
00000000002a41b0 T __ZdaPv
00000000002a41f0 T __ZdaPvRKSt9nothrow_t
00000000002a4190 T __ZdlPv
00000000002a41d0 T __ZdlPvRKSt9nothrow_t
00000000002a4060 T __Znam
00000000002a4130 T __ZnamRKSt9nothrow_t
00000000002a3ff0 T __Znwm
00000000002a40d0 T __ZnwmRKSt9nothrow_t
...
Run Code Online (Sandbox Code Playgroud)
您应该构建,-fvisibility=hidden然后只导出您想要的.在这里阅读:
http://gcc.gnu.org/wiki/Visibility
它还解释说-fvisibility-inlines-hidden.许多大型库(例如Qt)都使用它.好处是相当可观的.