更新:我正在使用linux上的GNU运行时。 在Apple运行库的MacOS上不会发生此问题。
更新2:我编译了MacOS上的GNU运行时,并用它构build了这个例子。 GNU运行时在MacOS上不会发生该错误。 我会说问题是glibc(因为backtrace和backtrace_symbols是glibc扩展)。
当使用backtrace和backtrace_symbols在GCC编译的Objective-C应用程序中打印backtrace_symbols ,我没有得到任何Objective-C符号。 只有文件名,地址和C符号出现。
我用-g编译,并与-rdynamic 。
在linux GCC中没有理由“初始化元素不是常量”错误,编译C
如何更新到C ++ 11?
STL容器内存问题
静态链接整个程序
编译一个代码有一个函数gethostbyname的静态二进制文件
我的testing应用程序
voID _printTrace() { voID *addr[1024]; int aCount = backtrace(addr,1024); char **frameStrings = backtrace_symbols(addr,aCount); for (int i = 0; i < aCount; i++) { printf("%sn",frameStrings[i]); } free(frameStrings); } @interface TheObject + (voID)_printTrace; + (voID)printTrace; @end @implementation TheObject + (voID)_printTrace { _printTrace(); } + (voID)printTrace { [self _printTrace]; } @end voID printTrace() { [TheObject printTrace]; } int main(int argc,char **argv) { printTrace(); return 0; }
它的输出:
./test.bin(_printTrace+0x1f) [0x8048e05] ./test.bin() [0x8048e60] ./test.bin() [0x8048e8b] ./test.bin(printTrace+0x34) [0x8048ec5] ./test.bin(main+0xf) [0x8048eda] /lib/libc.so.6(__libc_start_main+0xe5) [0xb7643bb5] ./test.bin() [0x8048b51]
有没有办法让Objective-C符号出现在这个回溯?
使用散列样式SYSV编译libstdc ++
从OS X交叉编译到linux
有没有办法在运行时修改linux C程序中的函数的代码?
警告C4996:与POSIX上的GCC相比,此function或variables可能不安全
在gcc中禁用可变长度的自动数组
dladdr()仅报告全局和弱符号。 但是所有的Objective-C函数符号都是本地的:
$ readelf -s so_backtrace Symbol table '.dynsym' contains 29 entrIEs: … Symbol table '.symtab' contains 121 entrIEs: Num: Value Size Type Bind Vis Ndx name … 49: 08048a01 13 FUNC LOCAL DEFAulT 14 _c_TheObject___printTrace 50: 08048a0e 47 FUNC LOCAL DEFAulT 14 _c_TheObject__printTrace …
您可以通过查看GNU libc源代码来验证本地符号是否永远不会返回。 backtrace_symbols()在sysdeps / generic / elf / backtracesyms.c中定义。 它依赖于在elf / dl-addr.c中定义的_dl_addr()来为它提供符号名称。 最终调用determine_info() 。 如果可以的话,它使用GNU哈希表 ,它不包含本地符号。
49 /* We look at all symbol table entrIEs referenced by the hash 50 table. */ … 60 /* The hash table never references local symbols so 61 we can omit that test here. */
如果GNU哈希表不存在,则回退到标准哈希表。 这包括了所有的符号,但是这个determine_info()代码过滤掉了除了全局符号和弱符号之外的所有符号:
90 if ((ELFW(ST_BIND) (symtab->st_info) == STB_GLOBAL 91 || ELFW(ST_BIND) (symtab->st_info) == STB_WEAK)
为了象征Objective-C函数地址,您必须自己执行查找,而不是过滤掉本地函数符号。 此外,您必须对Objective-C函数符号进行_c_TheObject___printTrace ,才能将_c_TheObject___printTrace恢复为+[TheObject _printTrace] 。
GNUstep的NSException实现不使用backtrace ,而是使用libbfd (二进制文件描述符)。 我认为这个工作的功能叫做static voID find_address ,你可以在这里查看。 使用这个微不足道的例子,我得到了下面的结果。
#include <Foundation/Foundation.h> @interface Test : NSObject {} + (voID) test; @end @implementation Test + (voID) test { Class GsstackTrace = objc_getClass("GsstackTrace"); ID stack = [GsstackTrace currentStack]; for (int i = 0; i < [stack frameCount]; i++) { NSLog (@"%@",[[stack frameat:i] function]); } } @end int main(int argc,char **argv) { NSautoreleasePool *pool = [[NSautoreleasePool alloc] init]; [Test test]; [pool release]; return 0; }
输出(使用调试符号编译时):
2010-10-18 14:14:46.188 a.out[29091] +[GsstackTrace currentStack] 2010-10-18 14:14:46.190 a.out[29091] +[Test test] 2010-10-18 14:14:46.190 a.out[29091] main 2010-10-18 14:14:46.190 a.out[29091] __libc_start_main
您可能能够分开GsstackTrace 。 这是一个“私有”类(这就是为什么我需要使用objc_getClass ,你也会得到很多无法识别的选择器警告),但它似乎包含了读取Objective-C类名所需的所有代码。
GNUstep在Ubuntu 9.04上测试,配置了--enable-deBUG (所以GSFunctionInfo包含在构建中)。
我希望你需要问ObjC运行时间的地址来获取符号信息。 例如,从backtrace()返回的地址可能被传递给像object_getClass()这样的类。 我还没有尝试过这个,但是在这种情况下,我会在这里看看。
总结以上是内存溢出为你收集整理的为什么回溯不包含Objective-C符号而不pipe-rdynamic?全部内容,希望文章能够帮你解决为什么回溯不包含Objective-C符号而不pipe-rdynamic?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)