iOS开发日常笔记(中级)
iOS开发日常笔记(中级)
-
Other Linker Flags常用的修饰词说明:
-
-ObjC
:对于ObjC
,官方解释如下:This flag causes the linker to load every object file in the library that defines an Objective-C class or category. While this option will typically result in a larger executable (due to additional object code loaded into the application), it will allow the successful creation of effective Objective-C static libraries that contain categories on existing classes. 简单的说就是ObjC会把静态库中所有的类和分类都链接进可执行文件,但是它不会去检查此类是否重复了,所以才会出现duplicate symbols的错误
-
-force_load
:这个的作用其实跟ObjC
是类似的。它是只指定某一个静态库才执行链接所有类和分类的操作,而ObjC
表示的是所有静态库 -
开发中会遇到
duplicate symbols
的问题,所以理想的状态就是不使用ObjC,只有包含分类的静态库才使用-force_load
,这样既能避免一些不必要的文件使包变大,又能使出现duplicate symbols
的概率减小。为什么只是减小呢?因为如果你这个静态库里即有重复文件又存在分类,那只能使用-force_load,同时那个重复的类也链接进来了,这样
duplicate symbols
就还会出现
-
-
符号表和编译链:
-
一个程序从代码到可执行文件要经历以下步骤:源代码 > 预处理器 > 编译器 > 汇编器 > 机器码 > 链接器 > 可执行文件
-
源代码经过一系列处理以后,会生成对应的
.o
文件,然后一个项目必然会有许多.o
文件,并且这些文件之间会有各种各样的联系,例如函数调用。链接器做的事就是把这些目标文件和所用的一些库链接在一起形成一个完整的可执行文件;通俗的讲,我们在源码中写的全局变量名
、函数名
或类名
在生成的*.o
对象文件中都叫做符号,存在一个叫做符号表的地方。 -
举个例子:
a.c
文件中写了一个函数叫foo()
,然后在main.c
文件中调用了foo()
函数,在将源码编译(生成)的对象文件a.o
时,对象文件中的符号表里保存着foo()
函数符号,并通过该符号可以定位到a.o
文件中关于foo()
方法的具体实现代码。- 链接器在链接生成最终的二进制程序的时候会发现main.o对象文件中引用了符号foo(),而foo()符号并没有在main.o文件中定义,所以不会存在与main.o对象文件的符号表中,于是链接器就开始检查其他对象文件,当检查到a.o文件中定义了符号foo(),于是就将a.o对象文件链接进来。这样就确保了在main.c中能够正常调用a.c中实现的foo()方法了。
-
导出库里面的符号表:
nm
命令,查看库的函数符号信息-
语法:nm [ -A ] [ -C ] [ -X {32|64|32_64}] [ -f ] [ -h ] [ -l ] [ -p ] [ -r ] [ -T ] [ -v ] [ -B | -P ] [ -e | -g | -u ] [ -d | -o | -x | -t Format ] File ...
-
语法说明请参考这个链接,我看写得挺详细的:https://blog.csdn.net/jingcheng345413/article/details/54969811
-
示例,列出
a.out
对象文件的静态和外部符号,请输入:nm -e a.out
-
-
-
Target Conditionals
- The system header
TargetConditionals.h
defines several macros which you can use from C and Objective-C to determine which platform you're using. - The values of the macros are: 7.0 When using the iOS 9.1, tvOS 9.0, watchOS 2.0, OS X 10.11 or newer SDKs:
Macro Mac iOS iOS simulator Watch Watch simulator TV TV simulator TARGET_OS_MAC
1 1 1 1 1 1 1 TARGET_OS_IPHONE
0 1 1 1 1 1 1 TARGET_OS_IOS
0 1 1 0 0 0 0 TARGET_OS_WATCH
0 0 0 1 1 0 0 TARGET_OS_TV
0 0 0 0 0 1 1 TARGET_OS_SIMULATOR
0 0 1 0 1 0 1 TARGET_OS_EMBEDDED
0 1 0 1 0 1 0 TARGET_IPHONE_SIMULATOR
0 0 1 0 1 0 - The system header
-
通过符号表还原崩溃调用堆信息:
-
首先得有对应的
xxx.dSYM
文件 -
找到
plCrashReporter.crashlog
文件,名字可能不一样,这个文件源自appstore或其它第三方工具 -
导出开发工具,等下需要用到,终端执行:
export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer
-
找到
symbolicatecrash
可执行文件:路径:/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/
,复制到某文件夹内,把第一步和第二步两文件也一起复制到同一文件下 -
当然上面那一步也可以写入终端脚本文件内:
// 如我终端默认脚本是:`.zshrc`,把下面内容追加到`.zshrc`中,这样下次就可以省略第四步操作了 export SYMBOLICATECRASH="/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/" export PATH=$SYMBOLICATECRASH:$PATH
-
还原崩溃信息:
symbolicatecrash plCrashReporter.crashlog xxx.dSYM > appName.log // > 代表输出,指定输出的文件:appName.log
-
常见 Exception Type 分析:
-
EXC_BAD_ACCESS:此类型的Excpetion是我们最长碰到的Crash,通常用于访问了不改访问的内存导致。一般EXC_BAD_ACCESS后面的"()"还会带有补充信息。
-
SIGSEGV: 通常由于重复释放对象导致,这种类型在切换了ARC以后应该已经很少见到了。
-
SIGABRT: 收到Abort信号退出,通常Foundation库中的容器为了保护状态正常会做一些检测,例如插入nil到数组中等会遇到此类错误。
-
SEGV:(Segmentation Violation),代表无效内存地址,比如空指针,未初始化指针,栈溢出等;
-
SIGBUS:总线错误,与 SIGSEGV 不同的是,SIGSEGV 访问的是无效地址,而 SIGBUS 访问的是有效地址,但总线访问异常(如地址对齐问题)
-
SIGILL:尝试执行非法的指令,可能不被识别或者没有权限
-
EXC_BAD_INSTRUCTION:此类异常通常由于线程执行非法指令导致
-
EXC_ARITHMETIC:除零错误会抛出此类异常
-
-
常见 Exception Code 分析:
- 0xbaaaaaad 此种类型的log意味着该Crash log并非一个真正的Crash,它仅仅只是包含了整个系统某一时刻的运行状态。通常可以通过同时按Home键和音量键,可能由于用户不小心触发
- 0xbad22222 当VOIP程序在后台太过频繁的激活时,系统可能会终止此类程序
- 0x8badf00d 程序启动或者恢复时间过长被watch dog终止
- 0xc00010ff 程序执行大量耗费CPU和GPU的运算,导致设备过热,触发系统过热保护被系统终止
- 0xdead10cc 程序退到后台时还占用系统资源,如通讯录被系统终止
- 0xdeadfa11 前面也提到过,程序无响应用户强制关闭
-
出处:http://www.cnblogs.com/nenhall/
如果您觉得阅读本文对您有帮助,请点击一下右下方的推荐按钮,您的推荐将是我写作的最大动力!
版权声明:本文为博主原创或转载文章,欢迎转载,但转载文章之后必须在文章页面明显位置注明出处,否则保留追究法律责任的权利。