我们已经建立了大量的开源软件在各种平台(Linux,在Windows,Mac OS X,32位和64位)数年无烦恼。 然而最近,在Mac OS X版本(64位)停止正常工作,并开始随机崩溃。 它与Mac OS X的我们的构建机器上10.8.2更新从10.7或多或少正值(但编译器工具链并没有改变,它仍然是LLVM-GCC 4.2.1)。
我们的应用程序是由一对夫妇的动态(共享)库和使用它们的许多可执行文件。 一个共享库的覆盖new
和delete
运营商的原因有多种。 在Mac OS X(和Linux),所有符号默认情况下出口的,包括我们的重载new
和delete
运算符。 在Mac OS X上的崩溃似乎与某些内存与一个内存子系统(不是我们的),然后通过我们自己的(和不兼容)释放分配delete
的实现。
该sanest溶液似乎是防止重载操作符从被连接到共享库的用户可见。 这可以通过两种方式来完成:标记与运营商__attribute__((visibility("hidden")))
或使用-unexported_symbols_list
链接器命令行选项,以防止被导出一些符号。 第一个解决方案不幸的是不起作用:GCC发出警告说,运营商已经宣布不同(在<new>
),因此属性将被忽略。 从我在各个地方的读数, 第二个解决方案似乎是正确的解决这个问题。 但是由于某些原因,我们不能使它发挥作用 。
当链接共享库,我们传递的-Wl,-unexported_symbols_list unexported_symbols_list.txt
选项G ++,这反过来应该传递给ld。 该unexported_symbols_list.txt
文件包含符号下面的列表:
__ZdaPv
__ZdaPvRKSt9nothrow_t
__ZdlPv
__ZdlPvRKSt9nothrow_t
__ZdlPvS_
__Znam
__ZnamRKSt9nothrow_t
__Znwm
__ZnwmPv
__ZnwmRKSt9nothrow_t
这些是所有变化new
和delete
,我们覆盖,并希望被隐藏。 我们做找不到这些符号nm libappleseed.dylib
然后unmangling使用符号名称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 [...]
不幸的是,尽管我们的一切努力似乎符号保持(如纳米所示)。
任何想法,我们在做什么错? 是否有另一种方法,我们可以尝试?
UPDATE 2012年12月19日:
我们的问题和解决方案应该很好覆盖在苹果这个技术说明: http://developer.apple.com/library/mac/#technotes/tn2185/_index.html (节“重写新/删除”)。
指针相关的源代码:
-
operator new
和operator delete
覆盖: allocator.cpp - 宏来控制在共享库符号可见: dllvisibility.h
的片段nm
构建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
...