0%

为什么学语法?

造句。说话写文章用短句子,长句子,不同短句又可以组合成新的长句。我们只有把长句子拆开来,直到拆到不能再继续拆了,否则句意会不完整的“基本句”,才好研究语法。如果基本句研究透了,长句子就是他们的组合。

什么是简单句(Simple Sentences)

把不能再拆的“基本句”称为简单句。除去“嗯!”,“哦”,“啊!”这样的感叹句,或者省略句或者向整句提问的问句,全部都是在说什么怎么样。绝大多数的句子粗略的分,就是“什么”+“怎么样”,而这个“什么”和“怎么样”分别对应了两个最基本的“句子成分”。两个最基本的句子成分是“主语(subject)”+“谓语(predicate)”。换句话说,几乎所有的英语句子结构都是主语+谓语。

主语(人/物)+谓语(动作(动词)/发生了什么事)

主语一般指“人/物”,不管抽象还是具体。谓语指的是“动作/发生了什么事”,这个动作并不是我们平时狭义说的要“动起来”的“动作”,这个广义的“动作”也就是我们所说的“动词”。

动词

1.可以独立完成的动作(主语+不及物动词)

这种没有承受者的动作,叫不及物动词。

1
2
Papa Rabbit sleeps.
兔老爹睡觉.

2.有1个动作的承受者(主语+单及物动词+宾语)

这种没有承受者就没有实际意义的动词属于“及物动词”。

1
2
Papa Rabbit likes you.
兔老爹喜欢你.

3.有2个动作承受者(主语+双及物动词+间接宾语+直接宾语)

1
2
Papa Rabbit teaches you English.
兔老爹教你英语。

4.只有1个动作承受者(主语+复杂及物动词+宾语+宾语补语)

1
2
Papa Rabbit considers you smart.
兔老爹认为你聪明。

5.非“动作”(主语+系动词+主语补语/表语)

把后者信息赋予前者,等同于赋值;把后者的状态赋予前者。赋予主语某种性质状态的“划等号”的动词被称为连系动词,连系动词也被称为系动词。系动词后面跟上主语补语,主语补语也叫表语。

1
2
3
4
5
6
7
8
9
10
11
Papa Rabbit is tall.
兔老爹是高的。

Papa Rabbit is in the room.
兔老爹在房间里。

Papa Rabbit looks tall.
兔老爹看起来高。

Papa Rabbit smells nice.
兔老爹闻上去香。

英语五种基本句型

五种基本句型

基本句型是不能再分的句子,缺少任何一种成分,句子的意义都不完整。五种基本句型其实就是在说动词,以及动词需要几个对象才能完整表达意思。

句子小结

英语中所有句子,当拆到不能再拆后,都是在说什么怎么样。什么是语法上的主语,怎么样是语法上的谓语,谓语都有一个核心动词叫谓语动词

谓语动词有五个基本类别,谓语动词的五个基本类别分别对应英语中的五种基本句型。

日常所说的主谓宾,其实只是以上五种基本句型中的一个类别,主语+谓语动词+宾语,也就是所谓的主谓宾结构

句子成分

1.主语

2.谓语动词

3.宾语

4.宾语补足语

5.主语补语(也叫表语)

6. 定语

1
2
The little white rabbit ate a large carrot.
这只小白兔吃了一根大胡萝卜。

这里的The little white就是rabbit的定语; a large就是carrot的定语。

7.状语

主要用来修饰谓语动词

1
2
The rabbit ate quickly.
兔子快速的吃。

quickly就是ate的状语

8.同位语

主要用来把主语或宾语再说一遍

1
2
Papa Rabbit, an English teacher,eats carrot.
兔老爹,一个英语老师,吃胡萝卜。

这里的an English teacher其实就是把Papa Rabbit用不同的方式再说一遍,在这里和主语算是同等地位。

简单句、复合句(并列句)、复杂句

到目前为止所说的都是简单句,简单句就是没法再拆成更多句子了。说话写文章可不全是简单句。我们会把简单句进行组合,形成复合句(compound sentences)复杂句(complex sentences)compound sentences是简单句的叠加,句子和句子是并列的关系,直接翻译为“复合句”,但是有的语法书上的术语是“并列句”。complex sentence说白了就是把一个句子套在另一个句子里,甚至一个句子套的一个句子还能再套一个句子,一直套下去。这是一种从属关系。complex sentence直接翻译是复杂句。在这里,一个句子套另一个句子,在英语语法上分别叫做主句(main clause)和从句(subordinate clause)。从句说白了就是把简单句修改一下来充当另一个句子的句子成分。比如,我们修改一个简单句,它可以作为另外一个句子的主语,这就是主语从句,依此内推,可以得到补语从句、宾语从句、表语从句、同位语从句,这几种从句都有名次性质,所以又被称为名词性从句,其他的还有定语从句和状语从句。

词性(词类)

同一类句子成分里可能有不同的词类

1.名词(nouns,表人和物)

1
2
Papa Rabbit is a rabbit.
兔老爹是只兔子。

这里的rabbit就是名词

2.冠词(articles,英语中说明人和事物)

1
2
Papa Rabbit is a rabbit.
兔老爹是只兔子。

这里的a就是冠词

3.代词(pronouns,替代人和物)

1
2
I am a rabbit.
我是只兔子。

这里的I就是代词

4.形容词(adjectives,形容人和物)

1
2
I am a smart rabbit.
我是只聪明的兔子。

这里的smart就是形容词

5.数词(numerals,表数量)

1
2
I ate two carrots.
我吃了两根胡萝卜。

这里的two就是数词

6.副词(adverbs,修饰动词或形容词)

1
2
I ate two carrots quickly.
我很快地吃了两根胡萝卜。

这里的quickly就是副词

7.介词(prepositions,表示和其他词关系的词)

1
2
I ate two carrots with chopsticks.
我用筷子吃了两根胡萝卜。

这里的with就是介词

8.叹词(interjections,表感叹)

1
2
Ah,the carrot is tasty!
啊,胡萝卜好美味!

这里的Ah就是叹词

9.连词(conjunctions,连接词和句)

1
2
I ate two carrots and a potato, because I was hungry.
我吃了两根胡萝卜和一个马铃薯,因为我饿了。

以上词类和动词一起,便是英语的十大词类

谓语动词的“三大本领”

1.动作时间(Tense)

1
2
3
4
现在
过去
将来
过去将来

2.动作状态(Aspect)

1
2
3
4
一般
完成
进行
完成进行

将动作时间和动作状态排列组合,理论上就有16种可能的时态

3.动作假设,情感(Mood,语法语气,并非说话语气)

1
2
3
4
5
6
7
8
If I were a rabbit...
(虚拟语气,用来表示意愿,和事实相反的假设等)

I ate a carrot and...
(陈述语气,)

Eat this carrot and...
(祈使语气)

以上三个特点分别称为动词的Tense、Aspect、Mood,合称TAM。英语的谓动词本身往往不能独立完成刚才说的那些本领,而且谓语动词独自也无法完成比如表示否定,可能性,必须性等意思。想让谓语动词充分发挥,我们必须用到另一类经常和动词一起用的词,帮助“完成任务”。它们就是“助动词”,auxiliary verbs。

助动词(auxiliary verbs)

1
2
3
4
5
6
7
(协助)表示“吃过了(完成)”  ->  have -> have eaten
(协助)表示“正在吃(进行)” -> be -> is eating
(协助)表示“被吃” -> be -> is eaten
(协助)表示“有能力吃” -> can -> can eat
(协助)表示“有可能吃” -> might -> might eat
(协助)表示“有义务吃” -> must -> must eat
(协助)表示“不吃(否定)” -> do -> do not eat

以上的can,might, must也被称为“情态动词”,可归类在“助动词”里–但是也有语法体系把情态动词单独归类–这是分类的不同,并不影响理解。但是还有个麻烦的事,就是很多助动词特别喜欢伪装,它们除了做助动词(没有实义,只是帮助谓语动词而已),还可以做实义动词,甚至还有其他词性。比如can还可以是易拉罐,might可以是力量,musty可以是发霉的,do可以是做某事,have可以是拥有,be可以是存在。这些也恰恰是容易让人混乱的地方。所以千万不要把助动词和它的其他身份(作实义动词时)弄混淆。

非谓语动词

动词除了可以在句子中充当谓语,还可以充当主语、宾语、宾语补语、主语补语、定语等,只不过需要把谓语动词修改成非谓语动词,非谓语动词可以充当除谓语动词以外的所有句子成分。不仅如此,非谓语动词几乎可以取代所有的从句,从而简化句子。只不过非谓语动词不再具有表示动作时间、状态、语态、语气的功能,也就是非谓语动词丧失了时态、语气、语态这些本领了。

非谓语动词有哪些:动词不定式、现在分词、动名词、过去分词

英语语法概述

英语的核心是动词,分为谓语动词和非谓语动词,谓语动词分为5种,分别决定了简单句(不能再拆)的5种基本句型,同时也囊括以下句子成分:主语、谓语动词、宾语、宾语补语、主语补语(表语)。除此之外,句子成分还有:定语、状语、同位语。简单句可以组合成并列关系的“复合句”以及从属关系的“复杂句”,后者包括主句和从句,从句可以充当所有除谓语动词以外的句子成分。句子成分可以由不同词类充当,分别是:名词、代词、冠词、形容词、数词、副词、介词、叹词、连词。谓语动词可以表达动作的时间,状态,语气等,但是需要用到助动词(包含情态动词)。助动词还能帮助否定动词,表达动词的被动,可能性,义务性… 非谓语动词可以视作“改动后”的谓语动词,可以充当除谓语动词外的所有句子成分,取代几乎所有从句,简化句子。

为什么要将Swift Package编译成XCframework?

这是一个困扰我很久的问题,问题产生的背景是多个Swift Package Manager创建的独立package,希望组合成一个SDK,这些package有些是第三方的,比如Alamofire、SwiftyJSON,也有自己写的package,自己写的package是依赖第三方package,现在想把自己写的package打包成XCFramework提供给别人使用,如何在不改动依赖情况下,将自己写的package和第三方的package都打包成XCframework?

简单理解一下需求,就是需要将SPM Package及其依赖的第三方SPM Package打包成XCFramework提供给别人使用。

有哪些解决方案?

方案1: swift-create-xcframework

swift-create-xcframeworkgithub上一个包装xcodebuild命令的命令行项目,通过这个命令行项目,你可以将自己写的SPM Package及其依赖的第三方SPM Package都打包成XCFramework项目地址

方案1示例

第一步:新建Package,然后编写Package.swift,设置第三方依赖

第二步:编写Package中的代码

编写代码,引用图片资源

第三步:在Package根目录,安装swift-create-xcframework

1
2
$ cd MyLibrary
$ brew install segment-integrations/formulae/swift-create-xcframework

第四步:查询Package中的Target

1
$ swift create-xcframework --list-products

第五步:编译打包Package中的全部target,多个target以空格分开

1
$ swift create-xcframework MyLibrary Alamofire

编译完成的截图

第六步:编译完成后会在Package根目录生成对应targetXCFramework文件

第七步:编写Demo测试生成后的XCFramework文件

编写代码测试xcframework

注意:swift-create-xcframework不是万能的,虽然它可以把自己写的SPM Package和Package依赖的第三方包都打包成XCFramework,但是如果自己的包和第三方的包里面引用了图片等资源,这些资源是不会打包进XCFramework的!!所以需要图片资源的可以继续看方案2。

方案2:自己编写脚本

第一步:编写打包脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#!/bin/bash

set -x
set -e

# Pass scheme name as the first argument to the script
NAME=$1

# Build the scheme for all platforms that we plan to support
for PLATFORM in "iOS" "iOS Simulator"; do

case $PLATFORM in
"iOS")
RELEASE_FOLDER="Release-iphoneos"
;;
"iOS Simulator")
RELEASE_FOLDER="Release-iphonesimulator"
;;
esac

ARCHIVE_PATH=$RELEASE_FOLDER

# Rewrite Package.swift so that it declaras dynamic libraries, since the approach does not work with static libraries
perl -i -p0e 's/type: .static,//g' Package.swift
perl -i -p0e 's/type: .dynamic,//g' Package.swift
perl -i -p0e 's/(library[^,]*,)/$1 type: .dynamic,/g' Package.swift

xcodebuild archive -workspace . -scheme $NAME \
-destination "generic/platform=$PLATFORM" \
-archivePath $ARCHIVE_PATH \
-derivedDataPath ".build" \
SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES

FRAMEWORK_PATH="$ARCHIVE_PATH.xcarchive/Products/usr/local/lib/$NAME.framework"
MODULES_PATH="$FRAMEWORK_PATH/Modules"
mkdir -p $MODULES_PATH

BUILD_PRODUCTS_PATH=".build/Build/Intermediates.noindex/ArchiveIntermediates/$NAME/BuildProductsPath"
RELEASE_PATH="$BUILD_PRODUCTS_PATH/$RELEASE_FOLDER"
SWIFT_MODULE_PATH="$RELEASE_PATH/$NAME.swiftmodule"
RESOURCES_BUNDLE_PATH="$RELEASE_PATH/${NAME}_${NAME}.bundle"

# Copy Swift modules
if [ -d $SWIFT_MODULE_PATH ]
then
cp -r $SWIFT_MODULE_PATH $MODULES_PATH
else
# In case there are no modules, assume C/ObjC library and create module map
echo "module $NAME { export * }" > $MODULES_PATH/module.modulemap
# TODO: Copy headers
fi

# Copy resources bundle, if exists
if [ -e $RESOURCES_BUNDLE_PATH ]
then
cp -r $RESOURCES_BUNDLE_PATH $FRAMEWORK_PATH
fi

done

xcodebuild -create-xcframework \
-framework Release-iphoneos.xcarchive/Products/usr/local/lib/$NAME.framework \
-framework Release-iphonesimulator.xcarchive/Products/usr/local/lib/$NAME.framework \
-output $NAME.xcframework

第二步:保存编译脚本,并放到Package根目录中,给脚本加上可执行权限,然后打包

1
2
$ chmod +x build.sh
$ ./build.sh MyLibrary

编译打包截图:

编译打包成功截图:

最终生成的XCFramework包含资源文件

注意:自己写脚本打包虽然可以将资源文件打包进XCFramework,但是资源文件被放在了一个单独的Bundle里面,与Xcode生成的XCFramework还是不太一样。并且,脚本无法将依赖的库也打包成XCFramework,所以具体采用哪一个方案还要结合自己的情况选择。目前看来两种解决方案都有缺陷,造成这种缺陷的原因是,Xcode目前没有支持将SPM Package打包成XCFramework的功能,所以才有这么多偏方,如果哪天Xcode支持了这个功能,那这两个方法都可以被抛弃了。

案例Demo

MyLibrary代码下载

参考链接

swift-create-xcframework

swift-create-xcframework(已不再维护)

How to build Swift Package as XCFramework

通过 Swift Package 制作二进制库

使用Swift Package Manager为二进制目标添加包依赖

向Swift Package中添加资源文件

如何精确统计SDK体积?

客户端拿到的SDK可能是多个架构的,比如armv7、armv7s、i386、x86_64、arm64,而最终打到ipa里面却不可能包含这么多架构,中间经过裁剪优化,可能最终体积会大大减少。

我就碰到了一个类似的问题,升级sdk,单纯从.a和.framework的体积来计算升级前后的体积,结论是升级后,sdk体积会降低12.35M的大小。但是,打出ipa进行比对,发现升级后ipa反而增长2.1M。看到这样的结果,我也不知道如何解释。

查看Mach-O文件__TEXT段大小

1
$ xcrun size -lm <binary-path>

使用上面的指令,可以查看Mach-O文件Data部分结构和各Segment/Section的大小信息。

通过比较两个ipa文件中Mach-O文件__TEXT段的大小,发现升级后的Mach-O文件的确增大了3M左右。

开启LinkMap选项,使用LinkMap分析SDK大小

  • 普通项目,开启LinkMap,需要在XCode -> Project -> Build Settings -> 把Write Link Map File选项设为yes,并指定好linkMap的存储位置
  • Bazel项目,开启LinkMap,需要在.bazelrc配置文件中添加下面几行配置:
    1
    2
    3
    aquery --objc_generate_linkmap=1
    build --objc_generate_linkmap=1
    cquery --objc_generate_linkmap=1
    然后,找到Edit Scheme选项,切换到release模式,编译项目,获取到编辑后的Mach-O文件和LinkMap文件。如果不清楚LinkMap文件位置,可以在Xcode的编辑日志中搜索LinkMap关键字,编辑的时候会打印相关日志。

使用LinkMap文件分析SDK的大小

使用LinkMap分析工具来分析,选择LinkMap文件,勾选”分组解析”,点击开始,最终会列出全部的库文件所占用的体积。

最终通过比较两个LinkMap分析的数据,发现升级之后 SDK体积确实增长了3.26M。

参考链接

今日头条优化实践: iOS 包大小二进制优化,一行代码减少 60 MB 下载大小
深入探索 iOS 包体积优化
iOS性能优化-包大小+linkMap分析和查找未使用类和方法
iOS使用LinkMap分析包大小
LinkMap分析工具

背景

周六打开电脑发现,密码怎么输都不对,无法登录电脑。一周没关机了,周五下班关机了,结果开起来密码忘记了。幸运的是,我在网上搜索相关的解决办法,很快就解决了我的问题,在这里记录一下哈~

解决办法

1.重启电脑,长按开机键,进入恢复模式

由于我的电脑是Macbook M1带Touch Bar的款式,在尝试网上长按Command + R无效后,长按开机键进入了回复模式,大概的界面是这样的。

2.选择实用工具菜单,打开终端

具体操作可以见上图。

3.输入resetpassword命令,重置密码

在终端直接输入resetpassword, 回车之后,会出现界面,提示重置密码。

4.Deactivate Mac

不知道是不是系统原因,我的电脑提示“在重置密码之前,需要先Deactivate Mac”,我就按照提示点了“Deactivate Mac”,这个操作暂时不清楚是干什么用的,不过不影响我的个人数据,最终我的数据没有丢失。

5.开始重置密码

操作完“Deactivate Mac”后,我就来到了重置密码的界面,按照要求,重新设置电脑密码,重启后就可以正常登录电脑了。

参考链接

Mac系统忘记开机密码怎么办?

iOS 15以上Crash Log解析

iOS 15以前崩溃日志使用symbolicatecrash去解析,升级iOS 15以后,崩溃日志的组织格式有变化,变成JSON格式,需要使用以下的命令行解析崩溃日志:

1
python3 /Applications/Xcode.app/Contents/SharedFrameworks/CoreSymbolicationDT.framework/Versions/A/Resources/CrashSymbolicator.py -d ./xxSDK.framework.dSYM -o ./1.crash -p ./0.ips

解析前的崩溃日志(部分删减):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
-------------------------------------
Translated Report (Full Report Below)
-------------------------------------

Incident Identifier: 8ECE464B-8E3E-422E-AFD4-B1B8B2E431B6
CrashReporter Key: eff5650d2e2bf936e1812e4b2d38a5ed26bda190
Hardware Model: iPhone10,3
Process: bililive [12926]
Path: /private/var/containers/Bundle/Application/6E82AD84-A575-4423-822E-176FB3BBFEF6/bililive.app/bililive
Identifier: com.bilibili.live.broadcast
Version: 5.53.0 (5520010)
Code Type: ARM-64 (Native)
Role: Foreground
Parent Process: launchd [1]
Coalition: com.bilibili.live.broadcast [493]

Date/Time: 2022-09-23 14:58:08.5849 +0800
Launch Time: 2022-09-23 14:43:37.3104 +0800
OS Version: iPhone OS 15.6 (19G71)
Release Type: User
Baseband Version: 7.61.00
Report Version: 104

Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Triggered by Thread: 81

Application Specific Information:
abort() called


Last Exception Backtrace:
0 CoreFoundation 0x180d5fd1c __exceptionPreprocess + 216
1 libobjc.A.dylib 0x19857fee4 objc_exception_throw + 56
2 Foundation 0x18245bbbc NSAllocateMemoryPages + 196
3 Foundation 0x182409a24 -[_NSPlaceholderData initWithBytes:length:copy:deallocator:] + 148
4 UIKitCore 0x183321738 _UIImageRefFromData + 232
5 UIKitCore 0x183322478 -[UIImage _initWithData:preserveScale:cache:scale:] + 64
6 UIKitCore 0x1833997a8 +[UIImage imageWithData:] + 56
7 xxSDK 0x10c7ef920 0x10c730000 + 784672
8 xxSDK 0x10c7e44e8 0x10c730000 + 738536
9 xxSDK 0x10c7f7358 0x10c730000 + 815960
10 xxSDK 0x10c7f7310 0x10c730000 + 815888
11 xxSDK 0x10c7f14b8 0x10c730000 + 791736
12 xxSDK 0x10c7f87e4 0x10c730000 + 821220
13 xxSDK 0x10c7ec8b4 0x10c730000 + 772276
14 xxSDK 0x10c7ec1ec 0x10c730000 + 770540
15 xxSDK 0x10c7eb95c 0x10c730000 + 768348
16 libdispatch.dylib 0x180a20094 _dispatch_client_callout + 16
17 libdispatch.dylib 0x1809f7ab8 _dispatch_continuation_pop$VARIANT$armv81 + 432
18 libdispatch.dylib 0x180a0916c _dispatch_source_invoke$VARIANT$armv81 + 1560
19 libdispatch.dylib 0x1809fb380 _dispatch_lane_serial_drain$VARIANT$armv81 + 308
20 libdispatch.dylib 0x1809fbf44 _dispatch_lane_invoke$VARIANT$armv81 + 388
21 libdispatch.dylib 0x180a058e0 _dispatch_workloop_worker_thread + 608
22 libsystem_pthread.dylib 0x1dc014e10 _pthread_wqthread + 284
23 libsystem_pthread.dylib 0x1dc01493c start_wqthread + 8

Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0:
0 libsystem_kernel.dylib 0x1bb5abaac mach_msg_trap + 8
1 libsystem_kernel.dylib 0x1bb5ac07c mach_msg + 72
2 CoreFoundation 0x180cd3d88 __CFRunLoopServiceMachPort + 368
3 CoreFoundation 0x180cd8090 __CFRunLoopRun + 1160
4 CoreFoundation 0x180ceb250 CFRunLoopRunSpecific + 572
5 GraphicsServices 0x1a1826988 GSEventRunModal + 160
6 UIKitCore 0x1834eba94 -[UIApplication _run] + 1080
7 UIKitCore 0x183284fd4 UIApplicationMain + 336
8 ??? 0x1072735d8 main + 180
9 dyld 0x10ba9c4d0 start + 444

Thread 1 name: Dispatch queue: com.apple.root.default-qos
Thread 1:
0 libsystem_kernel.dylib 0x1bb5aee30 poll + 8
1 ??? 0x108095540 pollset_work(grpc_pollset*, grpc_pollset_worker**, long long) + 1016
2 ??? 0x1080c5274 cq_next(grpc_completion_queue*, gpr_timespec, void*) + 476
3 ??? 0x107fe6334 __27-[GRPCCompletionQueue init]_block_invoke_2 + 104
4 libdispatch.dylib 0x180a1f094 _dispatch_call_block_and_release + 24
5 libdispatch.dylib 0x180a20094 _dispatch_client_callout + 16
6 libdispatch.dylib 0x180a0474c _dispatch_root_queue_drain + 612
7 libdispatch.dylib 0x180a04dec _dispatch_worker_thread2 + 160
8 libsystem_pthread.dylib 0x1dc014dd4 _pthread_wqthread + 224
9 libsystem_pthread.dylib 0x1dc01493c start_wqthread + 8

Thread 2 name: com.apple.uikit.eventfetch-thread
Thread 2:
0 libsystem_kernel.dylib 0x1bb5abaac mach_msg_trap + 8
1 libsystem_kernel.dylib 0x1bb5ac07c mach_msg + 72
2 CoreFoundation 0x180cd3d88 __CFRunLoopServiceMachPort + 368
3 CoreFoundation 0x180cd8090 __CFRunLoopRun + 1160
4 CoreFoundation 0x180ceb250 CFRunLoopRunSpecific + 572
5 Foundation 0x1823f8eec -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 232
6 Foundation 0x182438000 -[NSRunLoop(NSRunLoop) runUntilDate:] + 88
7 UIKitCore 0x18346af00 -[UIEventFetcher threadMain] + 512
8 Foundation 0x182445bfc __NSThread__start__ + 792
9 libsystem_pthread.dylib 0x1dc016348 _pthread_start + 116
10 libsystem_pthread.dylib 0x1dc014948 thread_start + 8

Thread 80 name: Dispatch queue: com.bilibili.live.imageQueue.ai.2d
Thread 80:
0 libsystem_platform.dylib 0x1dc007884 _platform_memmove + 100
1 ??? 0x107000268 MNN::_blit(MNN::Tensor::InsideDescribe::Region const&, int, unsigned char const*, unsigned char*, void (*)(unsigned char*, unsigned char const*, int, int, int)) + 700
2 ??? 0x1077b878c -[BBLiveBCVirtualCvAnimate detect:pose:] + 100
3 ??? 0x1077bd6d8 -[BBLiveBCVirtualLiveAIManager imageDataWithFaceAnchor:] + 5456
4 ??? 0x1077bc0d0 __46-[BBLiveBCVirtualLiveAIManager _readARSession]_block_invoke + 44
5 libdispatch.dylib 0x180a1f094 _dispatch_call_block_and_release + 24
6 libdispatch.dylib 0x180a20094 _dispatch_client_callout + 16
7 libdispatch.dylib 0x1809fb4a4 _dispatch_lane_serial_drain$VARIANT$armv81 + 600
8 libdispatch.dylib 0x1809fbf44 _dispatch_lane_invoke$VARIANT$armv81 + 388
9 libdispatch.dylib 0x180a058e0 _dispatch_workloop_worker_thread + 608
10 libsystem_pthread.dylib 0x1dc014e10 _pthread_wqthread + 284
11 libsystem_pthread.dylib 0x1dc01493c start_wqthread + 8

Thread 81 name: Dispatch queue: com.bilibili.live.session.render
Thread 81 Crashed:
0 libsystem_kernel.dylib 0x1bb5b1bbc __pthread_kill + 8
1 libsystem_pthread.dylib 0x1dc020854 pthread_kill + 208
2 libsystem_c.dylib 0x18b4496ac abort + 124
3 libc++abi.dylib 0x198677dd8 abort_message + 128
4 libc++abi.dylib 0x19866855c demangling_terminate_handler() + 300
5 libobjc.A.dylib 0x1985858f8 _objc_terminate() + 124
6 ??? 0x106033cd8 BLYCPPExceptionTerminate() + 2044
7 libc++abi.dylib 0x198677274 std::__terminate(void (*)()) + 16
8 libc++abi.dylib 0x19867721c std::terminate() + 60
9 libdispatch.dylib 0x180a200a8 _dispatch_client_callout + 36
10 libdispatch.dylib 0x1809f7ab8 _dispatch_continuation_pop$VARIANT$armv81 + 432
11 libdispatch.dylib 0x180a0916c _dispatch_source_invoke$VARIANT$armv81 + 1560
12 libdispatch.dylib 0x1809fb380 _dispatch_lane_serial_drain$VARIANT$armv81 + 308
13 libdispatch.dylib 0x1809fbf44 _dispatch_lane_invoke$VARIANT$armv81 + 388
14 libdispatch.dylib 0x180a058e0 _dispatch_workloop_worker_thread + 608
15 libsystem_pthread.dylib 0x1dc014e10 _pthread_wqthread + 284
16 libsystem_pthread.dylib 0x1dc01493c start_wqthread + 8

Thread 82 name: AURemoteIO::IOThread
Thread 82:
0 ae_tob_channelstrip 0x10d25c338 mammon::algorithm::RNNoise48k::ComputeGRULayer(mammon::GRULayer const*, float*, float*) + 1400
1 ae_tob_channelstrip 0x10d25b85c mammon::algorithm::RNNoise48k::computeRNN(float*) + 620
2 ae_tob_channelstrip 0x10d25b85c mammon::algorithm::RNNoise48k::computeRNN(float*) + 620
3 ae_tob_channelstrip 0x10d25b534 mammon::algorithm::RNNoise48k::compute(float*, float*, float) + 188
4 ae_tob_channelstrip 0x10d2571ac mammon::RNNoise48k::Impl::blockProcess(std::__1::vector<mammon::Bus, std::__1::allocator<mammon::Bus> >&) + 444
5 ae_tob_channelstrip 0x10d25564c mammon::RingBufferWrapper<mammon::RNNoise48k::Impl>::processWithRingbuffer(std::__1::vector<mammon::Bus, std::__1::allocator<mammon::Bus> >&) + 856
6 ae_tob_channelstrip 0x10d13a0ac sami::bl::EffectProcessorModel::process(sami::ProcessData&) + 88
7 ae_tob_channelstrip 0x10d134ebc sami::bl::AudioChannelStripProcessorImpl::process(sami::ProcessData&) + 752
8 ??? 0x1077957ac -[BBLiveBCIAudioChannelStrip processStereoAudioBuffer:dataInL:dataInR:samples:bufferLength:] + 764
9 ??? 0x107795448 -[BBLiveBCIAudioChannelStrip processInterleavedAudioBuffer:channels:samples:bufferLength:] + 312
10 ??? 0x107794318 -[BBLiveBCChannelStripAdapter process:numSamples:] + 68
11 ??? 0x107439d80 -[BBLiveBCCommonStreamBiz streamContainer:audioDataInNumberFrames:intIOData:] + 280
12 ??? 0x1077761fc -[BBLiveBCBasePushStreamContainer audioCapture:didOutputIntBuffer:numberOfFrames:timeStamp:] + 184
13 xxSDK 0x10c7d6450 0x10c730000 + 681040
14 xxSDK 0x10c7d7efc 0x10c730000 + 687868
15 libEmbeddedSystemAUs.dylib 0x1bfc041ec AURemoteIO::PerformIO(unsigned int, unsigned int, unsigned int, AudioTimeStamp const&, AudioTimeStamp const&, AudioBufferList const*, AudioBufferList*, int&) + 1100
16 libEmbeddedSystemAUs.dylib 0x1bfc0c6c4 _XPerformIO + 336
17 libAudioToolboxUtility.dylib 0x198ea36f0 mshMIGPerform + 260
18 libAudioToolboxUtility.dylib 0x198ea2e44 MSHMIGDispatchMessage + 36
19 libEmbeddedSystemAUs.dylib 0x1bfc03bb0 void* caulk::thread_proxy<std::__1::tuple<caulk::thread::attributes, AURemoteIO::IOThread::IOThread(AURemoteIO&, caulk::thread::attributes const&, caulk::mach::os_workgroup const&)::'lambda'(), std::__1::tuple<> > >(void*) + 556
20 libsystem_pthread.dylib 0x1dc016348 _pthread_start + 116
21 libsystem_pthread.dylib 0x1dc014948 thread_start + 8

解析后的崩溃日志(有删减):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
{"app_name":"bililive","timestamp":"2022-09-23 14:58:14.00 +0800","app_version":"5.53.0","slice_uuid":"8ca14ef0-07db-338e-aa61-5b1ee6987aff","build_version":"5520010","platform":"2","bundleID":"com.bilibili.live.broadcast","share_with_app_devs":"0","is_first_party":"0","bug_type":"309","os_version":"iPhone OS 15.6 (19G71)","incident_id":"8ECE464B-8E3E-422E-AFD4-B1B8B2E431B6","name":"bililive"}
{
"uptime": 87000,
"procLaunch": "2022-09-23 14:43:37.3104 +0800",
"procRole": "Foreground",
"version": 2,
"userID": 501,
"deployVersion": 210,
"modelCode": "iPhone10,3",
"procStartAbsTime": 2076968516925,
"coalitionID": 493,
"osVersion": {
"isEmbedded": true,
"train": "iPhone OS 15.6",
"releaseType": "User",
"build": "19G71"
},
"captureTime": "2022-09-23 14:58:08.5849 +0800",
"incident": "8ECE464B-8E3E-422E-AFD4-B1B8B2E431B6",
"bug_type": "309",
"pid": 12926,
"procExitAbsTime": 2097867677644,
"cpuType": "ARM-64",
"procName": "bililive",
"procPath": "/private/var/containers/Bundle/Application/6E82AD84-A575-4423-822E-176FB3BBFEF6/bililive.app/bililive",
"bundleInfo": {
"CFBundleShortVersionString": "5.53.0",
"CFBundleVersion": "5520010",
"CFBundleIdentifier": "com.bilibili.live.broadcast"
},
"storeInfo": {
"deviceIdentifierForVendor": "0A423654-7A61-4479-B9EE-4C98F01B7F4D",
"thirdParty": true
},
"parentProc": "launchd",
"parentPid": 1,
"coalitionName": "com.bilibili.live.broadcast",
"crashReporterKey": "eff5650d2e2bf936e1812e4b2d38a5ed26bda190",
"basebandVersion": "7.61.00",
"isCorpse": 1,
"exception": {
"codes": "0x0000000000000000, 0x0000000000000000",
"rawCodes": [
0,
0
],
"type": "EXC_CRASH",
"signal": "SIGABRT"
},
"asi": {
"libsystem_c.dylib": [
"abort() called"
]
},
"lastExceptionBacktrace": [
{
"imageOffset": 601372,
"symbol": "__exceptionPreprocess",
"symbolLocation": 216,
"imageIndex": 1
},
{
"imageOffset": 85732,
"symbol": "objc_exception_throw",
"symbolLocation": 56,
"imageIndex": 22
},
{
"imageOffset": 502716,
"symbol": "NSAllocateMemoryPages",
"symbolLocation": 196,
"imageIndex": 8
},
{
"imageOffset": 166436,
"symbol": "-[_NSPlaceholderData initWithBytes:length:copy:deallocator:]",
"symbolLocation": 148,
"imageIndex": 8
},
{
"imageOffset": 3258168,
"symbol": "_UIImageRefFromData",
"symbolLocation": 232,
"imageIndex": 3
},
{
"imageOffset": 3261560,
"symbol": "-[UIImage _initWithData:preserveScale:cache:scale:]",
"symbolLocation": 64,
"imageIndex": 3
},
{
"imageOffset": 3749800,
"symbol": "+[UIImage imageWithData:]",
"symbolLocation": 56,
"imageIndex": 3
},
{
"imageOffset": 784672,
"imageIndex": 17,
"symbol": "-[xxSDKEAGLRenderProvider textureWithCGImage:]",
"symbolLocation": 95
},
{
"imageOffset": 738536,
"imageIndex": 17,
"symbol": "-[xxSDKImageLayer draw]",
"symbolLocation": 187
},
{
"imageOffset": 815960,
"imageIndex": 17,
"symbol": "-[xxSDKLayer __visitAtMilliseconds:]",
"symbolLocation": 463
},
{
"imageOffset": 815888,
"imageIndex": 17,
"symbol": "-[xxSDKLayer __visitAtMilliseconds:]",
"symbolLocation": 391
},
{
"imageOffset": 791736,
"imageIndex": 17,
"symbol": "-[xxSDKEAGLRenderer(Context) __drawInRect:necessary:]",
"symbolLocation": 163
},
{
"imageOffset": 821220,
"imageIndex": 17,
"symbol": "-[xxSDKSceneRenderer __drawInRect:necessary:]",
"symbolLocation": 107
},
{
"imageOffset": 772276,
"imageIndex": 17,
"symbol": "-[xxSDKEAGLCanvas(Context) _drawInRect:necessary:]",
"symbolLocation": 203
},
{
"imageOffset": 770540,
"imageIndex": 17,
"symbol": "-[xxSDKEAGLCanvas(Context) _drawIfNecessary:]",
"symbolLocation": 135
},
{
"imageOffset": 768348,
"imageIndex": 17,
"symbol": "__34-[xxSDKEAGLCanvas(Lifecycle) _start]_block_invoke",
"symbolLocation": 35
},
{
"imageOffset": 409748,
"symbol": "_dispatch_client_callout",
"symbolLocation": 16,
"imageIndex": 6
},
{
"imageOffset": 244408,
"symbol": "_dispatch_continuation_pop$VARIANT$armv81",
"symbolLocation": 432,
"imageIndex": 6
},
{
"imageOffset": 315756,
"symbol": "_dispatch_source_invoke$VARIANT$armv81",
"symbolLocation": 1560,
"imageIndex": 6
},
{
"imageOffset": 258944,
"symbol": "_dispatch_lane_serial_drain$VARIANT$armv81",
"symbolLocation": 308,
"imageIndex": 6
},
{
"imageOffset": 261956,
"symbol": "_dispatch_lane_invoke$VARIANT$armv81",
"symbolLocation": 388,
"imageIndex": 6
},
{
"imageOffset": 301280,
"symbol": "_dispatch_workloop_worker_thread",
"symbolLocation": 608,
"imageIndex": 6
},
{
"imageOffset": 7696,
"symbol": "_pthread_wqthread",
"symbolLocation": 284,
"imageIndex": 7
},
{
"imageOffset": 6460,
"symbol": "start_wqthread",
"symbolLocation": 8,
"imageIndex": 7
}
],
"faultingThread": 81,
"threads": [
{
"id": 862161,
"queue": "com.apple.main-thread",
"frames": [
{
"imageOffset": 2732,
"symbol": "mach_msg_trap",
"symbolLocation": 8,
"imageIndex": 0
},
{
"imageOffset": 4220,
"symbol": "mach_msg",
"symbolLocation": 72,
"imageIndex": 0
},
{
"imageOffset": 28040,
"symbol": "__CFRunLoopServiceMachPort",
"symbolLocation": 368,
"imageIndex": 1
},
{
"imageOffset": 45200,
"symbol": "__CFRunLoopRun",
"symbolLocation": 1160,
"imageIndex": 1
},
{
"imageOffset": 123472,
"symbol": "CFRunLoopRunSpecific",
"symbolLocation": 572,
"imageIndex": 1
},
{
"imageOffset": 6536,
"symbol": "GSEventRunModal",
"symbolLocation": 160,
"imageIndex": 2
},
{
"imageOffset": 5134996,
"symbol": "-[UIApplication _run]",
"symbolLocation": 1080,
"imageIndex": 3
},
{
"imageOffset": 2617300,
"symbol": "UIApplicationMain",
"symbolLocation": 336,
"imageIndex": 3
},
{
"imageOffset": 4414977496,
"symbol": "main",
"symbolLocation": 180,
"imageIndex": 4
},
{
"imageOffset": 99536,
"symbol": "start",
"symbolLocation": 444,
"imageIndex": 5
}
]
},
{
"id": 862169,
"queue": "com.apple.root.default-qos",
"frames": [
{
"imageOffset": 15920,
"symbol": "poll",
"symbolLocation": 8,
"imageIndex": 0
},
{
"imageOffset": 4429796672,
"symbol": "pollset_work(grpc_pollset*, grpc_pollset_worker**, long long)",
"symbolLocation": 1016,
"imageIndex": 4
},
{
"imageOffset": 4429992564,
"symbol": "cq_next(grpc_completion_queue*, gpr_timespec, void*)",
"symbolLocation": 476,
"imageIndex": 4
},
{
"imageOffset": 4429079348,
"symbol": "__27-[GRPCCompletionQueue init]_block_invoke_2",
"symbolLocation": 104,
"imageIndex": 4
},
{
"imageOffset": 405652,
"symbol": "_dispatch_call_block_and_release",
"symbolLocation": 24,
"imageIndex": 6
},
{
"imageOffset": 409748,
"symbol": "_dispatch_client_callout",
"symbolLocation": 16,
"imageIndex": 6
},
{
"imageOffset": 296780,
"symbol": "_dispatch_root_queue_drain",
"symbolLocation": 612,
"imageIndex": 6
},
{
"imageOffset": 298476,
"symbol": "_dispatch_worker_thread2",
"symbolLocation": 160,
"imageIndex": 6
},
{
"imageOffset": 7636,
"symbol": "_pthread_wqthread",
"symbolLocation": 224,
"imageIndex": 7
},
{
"imageOffset": 6460,
"symbol": "start_wqthread",
"symbolLocation": 8,
"imageIndex": 7
}
]
},
{
"id": 867013,
"queue": "com.bilibili.live.imageQueue.ai.2d",
"frames": [
{
"imageOffset": 6276,
"symbol": "_platform_memmove",
"symbolLocation": 100,
"imageIndex": 15
},
{
"imageOffset": 4412408424,
"symbol": "MNN::_blit(MNN::Tensor::InsideDescribe::Region const&, int, unsigned char const*, unsigned char*, void (*)(unsigned char*, unsigned char const*, int, int, int))",
"symbolLocation": 700,
"imageIndex": 4
},
{
"imageOffset": 4420503436,
"symbol": "-[BBLiveBCVirtualCvAnimate detect:pose:]",
"symbolLocation": 100,
"imageIndex": 4
},
{
"imageOffset": 4420523736,
"symbol": "-[BBLiveBCVirtualLiveAIManager imageDataWithFaceAnchor:]",
"symbolLocation": 5456,
"imageIndex": 4
},
{
"imageOffset": 4420518096,
"symbol": "__46-[BBLiveBCVirtualLiveAIManager _readARSession]_block_invoke",
"symbolLocation": 44,
"imageIndex": 4
},
{
"imageOffset": 405652,
"symbol": "_dispatch_call_block_and_release",
"symbolLocation": 24,
"imageIndex": 6
},
{
"imageOffset": 409748,
"symbol": "_dispatch_client_callout",
"symbolLocation": 16,
"imageIndex": 6
},
{
"imageOffset": 259236,
"symbol": "_dispatch_lane_serial_drain$VARIANT$armv81",
"symbolLocation": 600,
"imageIndex": 6
},
{
"imageOffset": 261956,
"symbol": "_dispatch_lane_invoke$VARIANT$armv81",
"symbolLocation": 388,
"imageIndex": 6
},
{
"imageOffset": 301280,
"symbol": "_dispatch_workloop_worker_thread",
"symbolLocation": 608,
"imageIndex": 6
},
{
"imageOffset": 7696,
"symbol": "_pthread_wqthread",
"symbolLocation": 284,
"imageIndex": 7
},
{
"imageOffset": 6460,
"symbol": "start_wqthread",
"symbolLocation": 8,
"imageIndex": 7
}
]
},
{
"triggered": true,
"id": 867020,
"threadState": {
"x": [
{
"value": 0
},
{
"value": 0
},
{
"value": 0
},
{
"value": 0
},
{
"value": 6851899041
},
{
"value": 11349401200
},
{
"value": 110
},
{
"value": 0
},
{
"value": 11349405696
},
{
"value": 2127063980205108692
},
{
"value": 512
},
{
"value": 11
},
{
"value": 0
},
{
"value": 1761605632
},
{
"value": 16
},
{
"value": 0
},
{
"value": 328
},
{
"value": 2
},
{
"value": 0
},
{
"value": 6
},
{
"value": 96699
},
{
"value": 11349405920
},
{
"value": 5254550832
},
{
"value": 272
},
{
"value": 0
},
{
"value": 11349405920
},
{
"value": 65544
},
{
"value": 10789536384
},
{
"value": 8426050240,
"symbolLocation": 0,
"symbol": "_dispatch_mgr_q"
}
],
"flavor": "ARM_THREAD_STATE64",
"lr": {
"value": 7986088020
},
"cpsr": {
"value": 1073741824
},
"fp": {
"value": 11349401056
},
"sp": {
"value": 11349401024
},
"esr": {
"value": 1442840704,
"description": " Address size fault"
},
"pc": {
"value": 7438277564,
"matchesCrashFrame": 1
},
"far": {
"value": 18446743979222697204
}
},
"queue": "com.bilibili.live.session.render",
"frames": [
{
"imageOffset": 27580,
"symbol": "__pthread_kill",
"symbolLocation": 8,
"imageIndex": 0
},
{
"imageOffset": 55380,
"symbol": "pthread_kill",
"symbolLocation": 208,
"imageIndex": 7
},
{
"imageOffset": 128684,
"symbol": "abort",
"symbolLocation": 124,
"imageIndex": 20
},
{
"imageOffset": 69080,
"symbol": "abort_message",
"symbolLocation": 128,
"imageIndex": 21
},
{
"imageOffset": 5468,
"symbol": "demangling_terminate_handler()",
"symbolLocation": 300,
"imageIndex": 21
},
{
"imageOffset": 108792,
"symbol": "_objc_terminate()",
"symbolLocation": 124,
"imageIndex": 22
},
{
"imageOffset": 4395842776,
"symbol": "BLYCPPExceptionTerminate()",
"symbolLocation": 2044,
"imageIndex": 4
},
{
"imageOffset": 66164,
"symbol": "std::__terminate(void (*)())",
"symbolLocation": 16,
"imageIndex": 21
},
{
"imageOffset": 66076,
"symbol": "std::terminate()",
"symbolLocation": 60,
"imageIndex": 21
},
{
"imageOffset": 409768,
"symbol": "_dispatch_client_callout",
"symbolLocation": 36,
"imageIndex": 6
},
{
"imageOffset": 244408,
"symbol": "_dispatch_continuation_pop$VARIANT$armv81",
"symbolLocation": 432,
"imageIndex": 6
},
{
"imageOffset": 315756,
"symbol": "_dispatch_source_invoke$VARIANT$armv81",
"symbolLocation": 1560,
"imageIndex": 6
},
{
"imageOffset": 258944,
"symbol": "_dispatch_lane_serial_drain$VARIANT$armv81",
"symbolLocation": 308,
"imageIndex": 6
},
{
"imageOffset": 261956,
"symbol": "_dispatch_lane_invoke$VARIANT$armv81",
"symbolLocation": 388,
"imageIndex": 6
},
{
"imageOffset": 301280,
"symbol": "_dispatch_workloop_worker_thread",
"symbolLocation": 608,
"imageIndex": 6
},
{
"imageOffset": 7696,
"symbol": "_pthread_wqthread",
"symbolLocation": 284,
"imageIndex": 7
},
{
"imageOffset": 6460,
"symbol": "start_wqthread",
"symbolLocation": 8,
"imageIndex": 7
}
]
},
{
"id": 867068,
"name": "AURemoteIO::IOThread",
"frames": [
{
"imageOffset": 1246008,
"symbol": "mammon::algorithm::RNNoise48k::ComputeGRULayer(mammon::GRULayer const*, float*, float*)",
"symbolLocation": 1400,
"imageIndex": 19
},
{
"imageOffset": 1243228,
"symbol": "mammon::algorithm::RNNoise48k::computeRNN(float*)",
"symbolLocation": 620,
"imageIndex": 19
},
{
"imageOffset": 1243228,
"symbol": "mammon::algorithm::RNNoise48k::computeRNN(float*)",
"symbolLocation": 620,
"imageIndex": 19
},
{
"imageOffset": 1242420,
"symbol": "mammon::algorithm::RNNoise48k::compute(float*, float*, float)",
"symbolLocation": 188,
"imageIndex": 19
},
{
"imageOffset": 1225132,
"symbol": "mammon::RNNoise48k::Impl::blockProcess(std::__1::vector<mammon::Bus, std::__1::allocator<mammon::Bus> >&)",
"symbolLocation": 444,
"imageIndex": 19
},
{
"imageOffset": 1218124,
"symbol": "mammon::RingBufferWrapper<mammon::RNNoise48k::Impl>::processWithRingbuffer(std::__1::vector<mammon::Bus, std::__1::allocator<mammon::Bus> >&)",
"symbolLocation": 856,
"imageIndex": 19
},
{
"imageOffset": 57516,
"symbol": "sami::bl::EffectProcessorModel::process(sami::ProcessData&)",
"symbolLocation": 88,
"imageIndex": 19
},
{
"imageOffset": 36540,
"symbol": "sami::bl::AudioChannelStripProcessorImpl::process(sami::ProcessData&)",
"symbolLocation": 752,
"imageIndex": 19
},
{
"imageOffset": 4420360108,
"symbol": "-[BBLiveBCIAudioChannelStrip processStereoAudioBuffer:dataInL:dataInR:samples:bufferLength:]",
"symbolLocation": 764,
"imageIndex": 4
},
{
"imageOffset": 4420359240,
"symbol": "-[BBLiveBCIAudioChannelStrip processInterleavedAudioBuffer:channels:samples:bufferLength:]",
"symbolLocation": 312,
"imageIndex": 4
},
{
"imageOffset": 4420354840,
"symbol": "-[BBLiveBCChannelStripAdapter process:numSamples:]",
"symbolLocation": 68,
"imageIndex": 4
},
{
"imageOffset": 4416839040,
"symbol": "-[BBLiveBCCommonStreamBiz streamContainer:audioDataInNumberFrames:intIOData:]",
"symbolLocation": 280,
"imageIndex": 4
},
{
"imageOffset": 4420231676,
"symbol": "-[BBLiveBCBasePushStreamContainer audioCapture:didOutputIntBuffer:numberOfFrames:timeStamp:]",
"symbolLocation": 184,
"imageIndex": 4
},
{
"imageOffset": 681040,
"imageIndex": 17,
"symbol": "-[xxSDKAudioCapture audioEngine:inNumberFrames:recordIntData:timeStamp:]",
"symbolLocation": 159
},
{
"imageOffset": 687868,
"imageIndex": 17,
"symbol": "captureCallback",
"symbolLocation": 295
},
{
"imageOffset": 12780,
"symbol": "AURemoteIO::PerformIO(unsigned int, unsigned int, unsigned int, AudioTimeStamp const&, AudioTimeStamp const&, AudioBufferList const*, AudioBufferList*, int&)",
"symbolLocation": 1100,
"imageIndex": 23
},
{
"imageOffset": 46788,
"symbol": "_XPerformIO",
"symbolLocation": 336,
"imageIndex": 23
},
{
"imageOffset": 9968,
"symbol": "mshMIGPerform",
"symbolLocation": 260,
"imageIndex": 24
},
{
"imageOffset": 7748,
"symbol": "MSHMIGDispatchMessage",
"symbolLocation": 36,
"imageIndex": 24
},
{
"imageOffset": 11184,
"symbol": "void* caulk::thread_proxy<std::__1::tuple<caulk::thread::attributes, AURemoteIO::IOThread::IOThread(AURemoteIO&, caulk::thread::attributes const&, caulk::mach::os_workgroup const&)::'lambda'(), std::__1::tuple<> > >(void*)",
"symbolLocation": 556,
"imageIndex": 23
},
{
"imageOffset": 13128,
"symbol": "_pthread_start",
"symbolLocation": 116,
"imageIndex": 7
},
{
"imageOffset": 6472,
"symbol": "thread_start",
"symbolLocation": 8,
"imageIndex": 7
}
]
}

SIGABRT类型的Crash可以找Last Exception Backtrace定位崩溃

由于这个崩溃类型是SIGABRT类型的崩溃,可以直接查找崩溃日志中的Last Exception Backtrace堆栈,比如本次的原始堆栈就是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Last Exception Backtrace:
0 CoreFoundation 0x180d5fd1c __exceptionPreprocess + 216
1 libobjc.A.dylib 0x19857fee4 objc_exception_throw + 56
2 Foundation 0x18245bbbc NSAllocateMemoryPages + 196
3 Foundation 0x182409a24 -[_NSPlaceholderData initWithBytes:length:copy:deallocator:] + 148
4 UIKitCore 0x183321738 _UIImageRefFromData + 232
5 UIKitCore 0x183322478 -[UIImage _initWithData:preserveScale:cache:scale:] + 64
6 UIKitCore 0x1833997a8 +[UIImage imageWithData:] + 56
7 xxSDK 0x10c7ef920 0x10c730000 + 784672
8 xxSDK 0x10c7e44e8 0x10c730000 + 738536
9 xxSDK 0x10c7f7358 0x10c730000 + 815960
10 xxSDK 0x10c7f7310 0x10c730000 + 815888
11 xxSDK 0x10c7f14b8 0x10c730000 + 791736
12 xxSDK 0x10c7f87e4 0x10c730000 + 821220
13 xxSDK 0x10c7ec8b4 0x10c730000 + 772276
14 xxSDK 0x10c7ec1ec 0x10c730000 + 770540
15 xxSDK 0x10c7eb95c 0x10c730000 + 768348
16 libdispatch.dylib 0x180a20094 _dispatch_client_callout + 16
17 libdispatch.dylib 0x1809f7ab8 _dispatch_continuation_pop$VARIANT$armv81 + 432
18 libdispatch.dylib 0x180a0916c _dispatch_source_invoke$VARIANT$armv81 + 1560
19 libdispatch.dylib 0x1809fb380 _dispatch_lane_serial_drain$VARIANT$armv81 + 308
20 libdispatch.dylib 0x1809fbf44 _dispatch_lane_invoke$VARIANT$armv81 + 388
21 libdispatch.dylib 0x180a058e0 _dispatch_workloop_worker_thread + 608
22 libsystem_pthread.dylib 0x1dc014e10 _pthread_wqthread + 284
23 libsystem_pthread.dylib 0x1dc01493c start_wqthread + 8

解析后的Last Exception Backtrace堆栈:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
"lastExceptionBacktrace": [
{
"imageOffset": 601372,
"symbol": "__exceptionPreprocess",
"symbolLocation": 216,
"imageIndex": 1
},
{
"imageOffset": 85732,
"symbol": "objc_exception_throw",
"symbolLocation": 56,
"imageIndex": 22
},
{
"imageOffset": 502716,
"symbol": "NSAllocateMemoryPages",
"symbolLocation": 196,
"imageIndex": 8
},
{
"imageOffset": 166436,
"symbol": "-[_NSPlaceholderData initWithBytes:length:copy:deallocator:]",
"symbolLocation": 148,
"imageIndex": 8
},
{
"imageOffset": 3258168,
"symbol": "_UIImageRefFromData",
"symbolLocation": 232,
"imageIndex": 3
},
{
"imageOffset": 3261560,
"symbol": "-[UIImage _initWithData:preserveScale:cache:scale:]",
"symbolLocation": 64,
"imageIndex": 3
},
{
"imageOffset": 3749800,
"symbol": "+[UIImage imageWithData:]",
"symbolLocation": 56,
"imageIndex": 3
},
{
"imageOffset": 784672,
"imageIndex": 17,
"symbol": "-[xxSDKEAGLRenderProvider textureWithCGImage:]",
"symbolLocation": 95
},
{
"imageOffset": 738536,
"imageIndex": 17,
"symbol": "-[xxSDKImageLayer draw]",
"symbolLocation": 187
},
{
"imageOffset": 815960,
"imageIndex": 17,
"symbol": "-[xxSDKLayer __visitAtMilliseconds:]",
"symbolLocation": 463
},
{
"imageOffset": 815888,
"imageIndex": 17,
"symbol": "-[xxSDKLayer __visitAtMilliseconds:]",
"symbolLocation": 391
},
{
"imageOffset": 791736,
"imageIndex": 17,
"symbol": "-[xxSDKEAGLRenderer(Context) __drawInRect:necessary:]",
"symbolLocation": 163
},
{
"imageOffset": 821220,
"imageIndex": 17,
"symbol": "-[xxSDKSceneRenderer __drawInRect:necessary:]",
"symbolLocation": 107
},
{
"imageOffset": 772276,
"imageIndex": 17,
"symbol": "-[xxSDKEAGLCanvas(Context) _drawInRect:necessary:]",
"symbolLocation": 203
},
{
"imageOffset": 770540,
"imageIndex": 17,
"symbol": "-[xxSDKEAGLCanvas(Context) _drawIfNecessary:]",
"symbolLocation": 135
},
{
"imageOffset": 768348,
"imageIndex": 17,
"symbol": "__34-[xxSDKEAGLCanvas(Lifecycle) _start]_block_invoke",
"symbolLocation": 35
},
{
"imageOffset": 409748,
"symbol": "_dispatch_client_callout",
"symbolLocation": 16,
"imageIndex": 6
},
{
"imageOffset": 244408,
"symbol": "_dispatch_continuation_pop$VARIANT$armv81",
"symbolLocation": 432,
"imageIndex": 6
},
{
"imageOffset": 315756,
"symbol": "_dispatch_source_invoke$VARIANT$armv81",
"symbolLocation": 1560,
"imageIndex": 6
},
{
"imageOffset": 258944,
"symbol": "_dispatch_lane_serial_drain$VARIANT$armv81",
"symbolLocation": 308,
"imageIndex": 6
},
{
"imageOffset": 261956,
"symbol": "_dispatch_lane_invoke$VARIANT$armv81",
"symbolLocation": 388,
"imageIndex": 6
},
{
"imageOffset": 301280,
"symbol": "_dispatch_workloop_worker_thread",
"symbolLocation": 608,
"imageIndex": 6
},
{
"imageOffset": 7696,
"symbol": "_pthread_wqthread",
"symbolLocation": 284,
"imageIndex": 7
},
{
"imageOffset": 6460,
"symbol": "start_wqthread",
"symbolLocation": 8,
"imageIndex": 7
}
]

Bugly dsym 文件命令行上传

由于本次崩溃线程是Thread 81,查找Thread 81堆栈,发现最终的堆栈是指向了BLYCPPExceptionTerminate(),这个是Bugly里面的函数,可见这个崩溃被Bugly拦截到了。后续可以直接去Bugly网站上看崩溃的堆栈,本次崩溃的堆栈最终和我们解析过后的Last Exception Backtrace堆栈。

这里附上Bugly上传dsym文件的命令:

1
java -jar buglyqq-upload-symbol.jar -appid xxx -appkey xxx -bundleid "com.xxx.xxx.xxx" -version 5520010 -platform IOS -inputSymbol /Users/tingyue/Downloads/buglyqq-upload-symbol-2/xxSDK.framework.dSYM

参考链接

iOS15之后苹果崩溃日志解析方法
EXC_CRASH (SIGABRT)
Bugly符号表工具下载

背景

MAC电脑下载大文件,我一般用的是Aria2,以前用过迅雷,但是不好用。下面简单介绍一下Aria2如何使用。

Aria2是什么?

Aria2是一个轻量级的多协议和多源命令行下载实用程序。它支持HTTP/HTTPS、FTP、SFTP、BitTorrent和Metalink。Aria2可以通过内置的JSON-RPC和XML-RPC接口进行操作。

上面这段描述来自于Aria2官网介绍的中文翻译。

Aria2怎么下载?

从官网可以直达github的下载地址,github上提供Windows和Linux的安装包,Mac端需要下载源码自行编译。

源码下载完成之后,解压,依次执行以下命令,即可编译完成。

1
2
3
$ cd aria2-1.36.0
$ ./configure
$ make

编译完成后,在src目录下会生成一个可执行文件aria2c,这个可执行文件就是我们所需的命令行工具。

如何使用Aria2?

使用URL地址直接下载:

1
$ aria2c http://example.org/mylinux.iso

每个主机使用2个连接下载:

1
$ aria2c -x2 http://a/f.iso

BT种子下载:

1
$ aria2c http://example.org/mylinux.torrent

磁链下载:

1
$ aria2c 'magnet:?xt=urn:btih:248D0A1CD08284299DE78D5C1ED359BB46717D8C'

下载文本文件中的URI:

1
$ aria2c -i uris.txt

高级用法

使用Aria2启用RPC后台监听

1
$ aria2c --enable-rpc --rpc-listen-all

下载Web版的UI工具操作下载

下载webui-aria2工具,执行以下命令:

1
2
3
$ git clone https://github.com/ziahamza/webui-aria2.git
$ cd webui-aria2
$ node node-server.js

node会在本地开启服务器,默认地址是:http://localhost:8888,下载文件截图如下:

支持文件、种子等内容下载,支持中文,基本满足日常下载需求

参考链接

aria2官网
aria2源码
webui-aria2

域名无法购买问题

众所周知,freenom是一个免费域名提供商,用户可以在上面注册域名并免费使用12个月。但是最近我遇到了一点小麻烦,就是我按照以前的经验购买,网站就是会提示我技术错误,截图如下:


今天无意间在网上发现一篇博文介绍freenom购买域名的注意事项,然后实践了一下,发现确实如博主所说,故此处记录分享一下。

如何解决

如果发现和我一样的问题,请不要慌张,问题的原因是:您的IP信息和注册freenom账号的时候的信息匹配不上,导致官方认为你是异常IP,无法正常购买。去个人中心“Edit Account Details”,修改自己的“City”、“State/Region”、“Country”信息,将信息修改成ipinfo检测到的信息。

freenom个人中心的detail信息截图:


完成上述的操作后再次发起购买,就可以购买成功,此处附上购买成功的截图。

freenom使用注意事项

  • freenom的免费域名千万千万🙅🏻‍♀️不要🙅🏻‍♀️用于生产环境,否则等你流量起来之后,freenom会被莫名其妙的把你网站给封了,然后卖给别人。
  • freenom免费域名是最多时长为 12 个月,默认是 3 个月,到期前 15 天我们要自动续期,否则就会被取消域名所有权,会被 freenom 回收,另外续期是免费的,不会像奸商一样续期要加钱。

freenom如何续费

参考链接

freenom免费域名自动续期和ddns
ipinfo

问题描述

上传pkg文件到App Store,出现错误提示The following executables must include the "com.apple.security.app-sandbox" entitlement with a Boolean value of true in the entitlements property list.

问题原因

pkg文件中包含一个未签名的可执行文件,导致上传App Store时报错。

解决方案

假设你的可执行文件是”myexe”
1.创建myexe.entitlements文件

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.inherit</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
</dict>
</plist>

2.执行命令行

1
codesign -f -s "$YOUR_CERTIFICATE_HERE" --entitlements "$THE_ENTITLEMENTS_PLIST" "$THE_EXECUTABLE"

$YOUR_CERTIFICATE_HERE 使用你电脑上的 3rd Party Mac Developer Application certificate
$THE_ENTITLEMENTS_PLISTmyexe.entitlements文件绝对路径
$THE_EXECUTABLE 是工程中可执行文件的绝对路径
以下列一个自己执行的命令行:

1
codesign -f -s "3rd Party Mac Developer Application: xxxx (xxx)" --entitlements "/Users/xxx/Documents/xxx/myexe.entitlements" "/Users/xxx/Documents/xxx/myexe"

查看可执行文件内部签名的命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
➜ codesign -d -vvv --entitlements :- aria2c
Executable=/Users/tingyue/Desktop/111/aria2c
Identifier=aria2c
Format=Mach-O thin (arm64)
CodeDirectory v=20400 size=37087 flags=0x20002(adhoc,linker-signed) hashes=1156+0 location=embedded
Hash type=sha256 size=32
CandidateCDHash sha256=bc0e6a53312c4313d8bcc993327d7db6bf38bc42
CandidateCDHashFull sha256=bc0e6a53312c4313d8bcc993327d7db6bf38bc4278628d1367def2a85e06cda2
Hash choices=sha256
CMSDigest=bc0e6a53312c4313d8bcc993327d7db6bf38bc4278628d1367def2a85e06cda2
CMSDigestType=2
CDHash=bc0e6a53312c4313d8bcc993327d7db6bf38bc42
Signature=adhoc
Info.plist=not bound
TeamIdentifier=not set
Sealed Resources=none
Internal requirements=none

参考链接

How can I code sign a bundled executable file in a mac app using xcode5
Error when trying to Sandbox with codesign command
对于 Mac 应用程序在使用 3rd 方应用程序开发人员证书进行签名时验证应用程序时出错:未启用应用程序沙箱。以下可执行文件必须包含布尔值为 t 的“com.apple.security.app-sandbox”权利
Embedding a Command-Line Tool in a Sandboxed App
Embedding Nonstandard Code Structures in a Bundle

GLFW是什么?

GLFW是一个开源的多平台库,用于桌面上的OpenGL、OpenGL ES和Vulkan开发。它提供了一个简单的API,用于创建窗口、上下文和表面,接收输入和事件。和GLFW类似功能的几个库是GLUT、SDL、SFML和GLFW。我使用的是GLFW,大多数库的配置方法和GLFW差不多。

GLEW是什么?

GLEW是一个跨平台C++扩展库,基于OpenGL图形接口。GLEW能自动识别你的平台上所支持的全部OpenGL高级扩展函数。只要包含一个glew.h头文件,你就能使用gl、glu、wgl、glx的全部函数。GLEW支持目前流行的各种操作系统(包括Windows、Linux、Mac OSX、FreeBSD、Irix 和 Solaris)。

安装GLFW 和 GLEW

1
2
brew install glfw3
brew install glew

安装完成之后,在/opt/homebrew/Cellar路径下可以看见glew和glfw。

GLAD是什么?

GLAD是一个开源库,帮助开发者确定OpenGL函数位置。

安装GLAD

打开GLAD网站https://glad.dav1d.de/,选择3.3以上Core配置,直接Generate下载即可。

下载完成后解压会得到include和src文件夹,include文件夹中有glad和KRH两个文件夹,src中只有一个glad.c文件。

将include下的文件夹,包括glad和KRH都拷贝到/usr/local/include路径下,方便后期配置。

在Xcode配置glew、glfw和glad的路径

在Xcode中配置好glew和glfw、glad的路径

新建项目

新建MAC命令行项目,然后到 build Setting -> Header Search Path 和 Library Search Path 添加相应的配置。

配置Header Search Path:
$(glew_header) 、$(glfw_header)、$(glad_header)

配置Library Search Path:
$(inherited) $(glew_lib) $(glfw_lib)

增加Build Phases配置:
添加glfw和glew的库的时候需要对应的路径

1
2
/opt/homebrew/Cellar/glew/2.2.0_1/lib
/opt/homebrew/Cellar/glfw/3.3.6/lib

删除原来的main文件,新建C++的main文件,并创建相应的header文件。如果使用到了GLAD,还需要将glad.c源文件拖到项目中。
测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
#include <iostream>

// GLEW
#define GLEW_STATIC
#include <GL/glew.h>

// GLFW
#include <GLFW/glfw3.h>


// Function prototypes
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);

// Window dimensions
const GLuint WIDTH = 800, HEIGHT = 600;

// Shaders
const GLchar* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 position;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"
"}\0";
const GLchar* fragmentShaderSource = "#version 330 core\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
"color = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";

// The MAIN function, from here we start the application and run the game loop
int main()
{
std::cout << "Starting GLFW context, OpenGL 3.3" << std::endl;
// Init GLFW
glfwInit();
// Set all the required options for GLFW
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

// Create a GLFWwindow object that we can use for GLFW's functions
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
glfwMakeContextCurrent(window);

// Set the required callback functions
glfwSetKeyCallback(window, key_callback);

// Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
glewExperimental = GL_TRUE;
// Initialize GLEW to setup the OpenGL Function pointers
glewInit();

// Define the viewport dimensions
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);


// Build and compile our shader program
// Vertex shader
GLint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// Check for compile time errors
GLint success;
GLchar infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// Fragment shader
GLint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// Check for compile time errors
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// Link shaders
GLint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// Check for linking errors
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);


// Set up vertex data (and buffer(s)) and attribute pointers
//GLfloat vertices[] = {
// // First triangle
// 0.5f, 0.5f, // Top Right
// 0.5f, -0.5f, // Bottom Right
// -0.5f, 0.5f, // Top Left
// // Second triangle
// 0.5f, -0.5f, // Bottom Right
// -0.5f, -0.5f, // Bottom Left
// -0.5f, 0.5f // Top Left
//};
GLfloat vertices[] = {
0.5f, 0.5f, 0.0f, // Top Right
0.5f, -0.5f, 0.0f, // Bottom Right
-0.5f, -0.5f, 0.0f, // Bottom Left
-0.5f, 0.5f, 0.0f // Top Left
};
GLuint indices[] = { // Note that we start from 0!
0, 1, 3, // First Triangle
1, 2, 3 // Second Triangle
};
GLuint VBO, VAO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
// Bind the Vertex Array Object first, then bind and set vertex buffer(s) and attribute pointer(s).
glBindVertexArray(VAO);

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);

glBindBuffer(GL_ARRAY_BUFFER, 0); // Note that this is allowed, the call to glVertexAttribPointer registered VBO as the currently bound vertex buffer object so afterwards we can safely unbind

glBindVertexArray(0); // Unbind VAO (it's always a good thing to unbind any buffer/array to prevent strange bugs), remember: do NOT unbind the EBO, keep it bound to this VAO


// Uncommenting this call will result in wireframe polygons.
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

// Game loop
while (!glfwWindowShouldClose(window))
{
// Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
glfwPollEvents();

// Render
// Clear the colorbuffer
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

// Draw our first triangle
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
//glDrawArrays(GL_TRIANGLES, 0, 6);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);

// Swap the screen buffers
glfwSwapBuffers(window);
}
// Properly de-allocate all resources once they've outlived their purpose
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
// Terminate GLFW, clearing any resources allocated by GLFW.
glfwTerminate();
return 0;
}

// Is called whenever a key is pressed/released via GLFW
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}

如果出现下图所示的效果,则环境配置成功

遇到的错误

提示dyld: Library not loaded: /opt/homebrew/opt/glfw/lib/libglfw.3.dylib,详细错误信息如下:

1
2
3
4
5
dyld: Library not loaded: /opt/homebrew/opt/glfw/lib/libglfw.3.dylib
  Referenced from: /Users/tingyue/Library/Developer/Xcode/DerivedData/测试opengl-cveeuitmqxwjawbhmdcvrxupnsvp/Build/Products/Debug/测试opengl
  Reason: no suitable image found.  Did find:
/opt/homebrew/opt/glfw/lib/libglfw.3.dylib: code signature in (/opt/homebrew/opt/glfw/lib/libglfw.3.dylib) not valid for use in process using Library Validation: mapped file has no Team ID and is not a platform binary (signed with custom identity or adhoc?)
/opt/homebrew/Cellar/glfw/3.3.6/lib/libglfw.3.3.dylib: code signature in (/opt/homebrew/Cellar/glfw/3.3.6/lib/libglfw.3.3.dylib) not valid for use in process using Library Validation: mapped file has no Team ID and is not a platform binary (signed with custom identity or adhoc?)

解决办法:
找到项目的Signing&Capabilities选项,然后勾选Disable Library Validation选项,重新运行起来就可以了。

Demo下载

下载Demo工程

参考链接

Mac下Xcode+OpenGL环境搭建
创建窗口

OpenGL是什么?

  • OpenGL是一个图形API规范,由Khronos组织制定并维护。
  • OpenGL规范严格规定了每个函数如何执行,以及它的输出值,没有规定实现细节。
  • OpenGL库的开发者通常是显卡的生产商,不同显卡对应的OpenGL库实现细节可能不同,但是他们的功能和结果都遵循OpenGL规范。

核心模式和立即渲染模式

  • 立即渲染模式(Immediate mode):早期OpenGL使用,也就是固定渲染管线(Fixed Pipeline),这个模式下绘制图形很方便。OpenGL的大多数功能都被库隐藏起来,开发者很少有控制OpenGL如何进行计算的自由。
  • 核心模式(Core-Profile):也称为可编程渲染管线(Programmable Pipline)。OpenGL3.2开始废弃立即渲染模式,并鼓励开发者在OpenGL的核心模式下进行开发。从OpenGL3.3开始,新版本都在此基础上引入了额外的功能,核心架构并没有改动。

状态机

  • OpenGL自身是一个巨大的状态机(State Machine):一系列的变量描述OpenGL此刻应当如何运行。OpenGL的状态通常被称为OpenGL上下文。我们通常使用如下途径去更改OpenGL状态:设置选项,操作缓冲。最后,我们使用当前的OpenGL上下文渲染。
  • 当使用OpenGL的时候,我们会遇到一些状态设置函数(例如:glClearColor(0.2f, 0.3f, 0.3f, 1.0f);),这类函数将会改变上下文。也会遇到状态使用函数(例如:glClear(GL_COLOR_BUFFER_BIT);),这类函数会根据当前OpenGL的状态执行一些操作。

图形渲染管线

在OpenGL中,任何事物都在3D空间中,而屏幕和窗口确是2D像素数组,这导致OpenGL的大部分工作都是把3D坐标转变为适应屏幕的2D像素。3D坐标转为2D像素的处理过程是由OpenGL的图形渲染管线(Graphics Pipeline)管理的。图形渲染管线可以被划分为两个主要部分:第一部分把你的3D坐标转换为2D坐标,第二部分是把2D坐标转变为实际的有颜色的像素。

  • 顶点着色器(Vertex Shader):图形渲染管线的第一部分是顶点着色器,他作用于每一个顶点,将输入的3分量向量坐标转换成4分量的向量坐标,生成每个顶点的最终位置,存储在gl_Position中。每个顶点执行一次。
  • 图元装配(Primitive Assembly):将顶点着色器输出的所有顶点作为输入,并将所有的点装配成指定图元的形状。
  • 几何着色器(Geometry Shader):图元装配阶段的输出会传递给几何着色器。几何着色器把图元形式的一系列顶点的集合作为输入,它可以通过产生新的顶点构造出新的图元来生成其他形状。
  • 光栅化(Rasterization Stage):在这个阶段里把图元映射为最终屏幕上相应的像素,生成片段(Fragment),供片段着色器(Fragment Shader)使用。在片段着色器运行之前会执行裁切(Clipping),裁切会丢弃超出你的视图以外的所有像素,用来提升效率。

    OpenGL中的一个片段是OpenGL渲染一个像素所需的所有数据。

  • 片段着色器(Fragment Shader):主要目的是计算一个像素的最终颜色,这也是OpenGL高级效果产生的地方。通常,片段着色器包含3D场景的数据(比如光照、阴影、光的颜色等等),这些数据可以被用来计算最终像素的颜色。
  • 测试与混合:在所有颜色确定以后,最终的对象会被传到测试和混合(Blending)阶段。这个阶段检测片段的对应深度和模板值,通过深度来判断像素是否被遮挡,是否应该丢弃。这个阶段也会检查alpha值,并对物体颜色进行混合。

大多数场合只需配置顶点和片段着色器就行,几何着色器是可选的,通常使用默认的几何着色器就行了。我们必须定义至少一个顶点着色器和一个片段着色器(因为GPU中没有默认的顶点/片段着色器)。

词汇表

  • GLAD: 一个拓展加载库,用来为我们加载并设定所有OpenGL函数指针,从而让我们能够使用所有(现代)OpenGL函数。
  • 视口(Viewport): 我们需要渲染的窗口。
  • 图形管线(Graphics Pipeline):一个顶点在呈现为像素之前经过的全部过程。
  • 着色器(Shader): 一个运行在显卡上的小型程序。很多阶段的图形管道都可以使用自定义的着色器来代替原有的功能。
  • 标准化设备坐标(Normalized Device Coordinates,NDC): 顶点在通过裁剪坐标系中裁剪与透视除法后最终呈现的坐标系。所有位置在NDC下-1.0到1.0的顶点将不会被丢弃并且可见。
  • 顶点缓冲对象(Vertex Buffer Object): 一个调用显存并存储所有顶点数据供显卡使用的缓冲对象。
  • 顶点数组对象(Vertex Array Object): 存储缓冲区和顶点属性状态。
  • 索引缓冲对象(Element Buffer Object): 一个存储索引供索引化绘制的使用的缓冲对象。
  • Uniform: 一个特殊类型的GLSL变量。它是全局的(在一个着色器程序中每一个着色器都能够访问uniform变量),并且只需要被设定一次。
  • 纹理(Texture): 一种包裹着物体的特殊类型的图像,给物体精细的视觉效果。
  • 纹理缠绕(Texture Wrapping): 定义一种当纹理顶点超出范围(0, 1)时,指定OpenGL如何采样纹理的模式。
  • 纹理过滤(Texture Filtering): 定义一种当有多种文素选择时指定OpenGL如何采样纹理的模式。这通常在纹理被放大情况下发生。
  • 多级渐远纹理(Mipmaps): 被存储的材质的一些缩小版本,根据观察者的距离会使用材质的合适大小。
  • 纹理单元(Texture Units): 通过绑定纹理到不同纹理单元从而允许多个纹理在同一对象上渲染。
  • 向量(Vector): 一个定义了在空间中方向或位置的数学实体。
  • 矩阵(Matrix): 一个矩形阵列的数学表达式。
  • GLM: 一个为OpenGL打造的数学库。
  • 局部空间(Local Space): 一个物体的初始空间。所有的坐标都是相对于物体原点的。
  • 世界空间(World Space): 所有坐标都是相对于全局原点的。
  • 观察空间(View Space): 所有的坐标都是从摄像机的视角观察的。
  • 裁剪空间(Clip Space): 所有的坐标都是从摄像机视角观察的,但是该空间应用了投影。这个空间应该是一个顶点坐标最终的空间,作为顶点着色器的输出。OpenGL负责处理剩下的事情(裁剪/透视除法)。
  • 屏幕空间(Screen Space): 所有的坐标都由屏幕视角来观察,坐标的范围是从0到屏幕的宽/高。
  • LookAt矩阵: 一种特殊类型的观察矩阵,它创建了一个坐标系,其中所有的坐标都根据从一个位置观察目标用户的旋转或平移。
  • 欧拉角(Euler Angles): 被定义为偏航角(Yaw),俯仰角(Pitch)和滚转角(Roll)从而允许我们通过这三个值构造任何3D方向。

参考链接

你好,三角形
Shader知识普及之:顶点着色器
顶点着色器、片段着色器、uniform变量