Rust 所有权规则简述

对于低级语言而言,对象的回收往往是一个难题。一个对象创建后,往往会在各个地方传递,由于对象的引用者们生命周期不尽相同,也就不知道何时、由谁来负责对象的回收。

Rust 所有权规则是如何解决这个问题的呢?它把对象分为可变对象和不可变对象,对象的引用者分为所有者和借用者。下面是我根据自己的理解做的总结:

  • 一个对象有且只能有一个所有者,对象的回收由其所有者负责,对象的所有权可以转移。

  • 借用分为可变借用和不可变借用:

    • 多个不可变借用可共存;
    • 可变借用不可和其他借用共存,无论借用是可变还是不可变;
    • 对象所有者不能在不可变借用前写对象,不能在可变借用前读写对象;
    • 可变对象可以有可变和不可变借用,不可变对象只能有不可变借用;
  • 对象的所有权转移时,对象的可变性可以发生更改。

不能共存指的是它们的作用域不能有交集。一个变量的作用域从声明的地方开始,到最后一次使用的位置结束,这一点和其他语言不同。

阅读全文 »

前言

Kotlin 中的协程是无栈协程,网上很多文章都说无栈协程一般都是通过状态机实现的,于是我打算利用反编译工具并结合协程库源码,来探究一下 Kotlin 到底是如何通过状态机实现协程的。

一个简单的示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
fun main() {
runBlocking {
val result = fun1()
println(result)
}
}

suspend fun fun1(): Int {
var localInt = 0
localInt += fun2()
localInt += fun3()
return localInt
}

suspend fun fun2(): Int = 1

suspend fun fun3(): Int {
delay(1000)
return 1
}
阅读全文 »

什么是跨源请求

先看同源 URL 定义:

如果两个 URL 的协议端口(如果有指定的话)和主机都相同的话,则这两个 URL 是同源的。这个方案也被称为“协议/主机/端口元组”,或者直接是“元组”。(“元组”是指一组项目构成的整体,具有双重/三重/四重/五重等通用形式。)

当网页发出请求的 URL 和网页的 URL 是非同源的,我们便说这个请求是跨源请求。安全起见,浏览器会对跨源请求做出限制。

为什么要对跨源请求进行限制

假如你曾经登录过银行网站 A,该网站会将 token 保存在你浏览器的 Cookies 中。某天你收到了一封来自钓鱼网站 B 的邮件,你点开链接打开了 B 网站,B 网站调用 A 网站的转账接口,企图将你在这家银行的钱转进他的帐户里。如果浏览器不对跨源请求做任何限制,A 网站的 Cookies 便会附带到转账请求中,请求就能顺利通过 A 网站服务器的身份验证,你的钱就被转走了。

为了解决这个问题,浏览器引入了 同源策略

阅读全文 »

前言

心血来潮打开了尘封已久的 switch,发现软件更新实在太慢,上网找了几种常用的加速方法,但最终都被 pass:

  • 更改 DNS 服务器,缺点是网速提升有限,大概在 34 Mbps 左右,大概提升 1 ~ 2 Mbps 左右 ,相对 switch 几百 M 几个 G 的游戏来说,依然是龟速。唯一的好处是不用借助其他设备。
  • 买加速器。对于喜欢折腾的人来说,花钱永远是最后的选择,况且我自己有梯子,干嘛花这个冤枉钱。
  • 把电脑上的代理通过局域网分享给 switch,然而发现网速的提升依然不高,虽然后来发现是 USB 无线网卡的问题,但不管怎样,电脑一直保持开机状态,就是为了给 switch 做代理,总感觉不太优雅。

要是能在路由器上跑代理就好了,不过现在的路由器不支持装插件,而且是公用的,不太适合去折腾。这时候突然想起了我还有个同样在吃灰的树莓派,如果能把这台树莓派变成一台软路由,再在这个软路由上跑代理,岂不美哉?对比几款软路由之后,我最终选择了 OpenWrt,一是因为它插件比较多,有更多可玩性,二是用户量大,教程多,遇到问题容易找到解决方案。

话不多说,开干。

阅读全文 »

P199: “默认情况下,如果可执行文件是动态连接的,那么 GCC 会使用 PIC 的方法来产生可执行文件的代码段部分,以便于不同的进程能够共享” 但我用 GCC 去编译 32 位可执行文件,加 -fPIC 和不加 -fPIC,编出的指令是有差别的:

-fPIC 对生成指令的影响

阅读全文 »

学习 vfork 的时候,看到这篇文章中的一个例子,觉得很有趣,就拷贝下来自己跑了一下,例子差不多长这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void fun1() {
vfork();
printf("%d\n", getpid());
}

void fun2() {
_exit(0);
}

int main() {

fun1();

printf("%d goes 1\n", getpid());

fun2();

printf("%d goes 2\n", getpid());

return 0;
}
阅读全文 »

前言

Gradle 的强大之处不在于它本身提供了多少功能,而是它的扩展性极强,开发者可以在构建脚本中定义任务,或者引入插件,将各式各样的任务集成到构建流程中。借助 Gradle 灵活的 DSL ,开发者很容易完成构建脚本的编写。但也正是由于 DSL 太过于灵活,gradle 脚本的语法经常让我们琢磨不透,无法从传统编程语言的角度去理解它。这篇文章将会结合源码探究 Gradle 的 dsl 实现原理,旨在帮助大家消除对于 Gradle 脚本语法的各种疑惑,更好地理解 Gradle。

走近 Groovy

我们知道,Gradle 是基于 Groovy 的,Groovy 是一门动态的 JVM 语言,Gradle 灵活的 DSL 就是建立在 Groovy 的动态性之上的。在探究 Gradle 之前,我们最好先对 Groovy 动态性的实现原理有一个初步的认知。

从一个简单的例子开始:

1
2
3
class A {}
A a = new A()
a.b = new Object()

如果这是一段 Java 代码,肯定会报错,因为找不到属性 b。但是在 Groovy 中就不一样了,上面这段代码在大概会编译成这个样子(实际上比这复杂,这是简化后的代码):

1
2
3
4
5
// groovy 脚本中定义的所有类都会自动实现 GroovyObject 
class A implements GroovyObject {
}
A a = new A()
a.setProperty("b", new Object())
阅读全文 »

前言

这两天为了破解魔百盒费了好大劲,看了好多帖子,好在最后破解成功了。为了让大家少走弯路,我把破解方法分享出来,希望能帮助到大家。

盒子型号

我的盒子型号是 CM201-2 长虹代工 (CH),具体信息见图片:

盒子信息

板子上的硬件信息是:CPU 型号是 HI3890MV300,闪存是 emmc。机型编码和牌照方不同应该没太大关系,大家可以先尝试一下,不行再说。

阅读全文 »

View 的焦点机制

约定:文章中的 View 有时是指狭义的 View.class,有时指的是 View.class 和 ViewGruop.class 的统称,具体含义根据上下文而定

和焦点相关的 xml 属性

在 xml 中,有两个比较重要的属性和焦点有关,它们是 focusable 和 focusableInTouchMode。前者决定这个 View 是否可获取焦点,如果它的值为 false,那么它就和焦点无缘了;后者决定这个 View 在触屏模式下是否可获取焦点,如果它的值为 false,那么即使 focusable 的值为 true,在触屏模式下它也无法获取焦点。比如 Button,如果我们通过外接键盘进行操作,我们会发现 Button 是可以获得焦点的,但是在触屏模式下,Button 是不可获取焦点的。所以我们可以知道 Button 的 focusable 属性默认为 true,而 focusableInTouchMode 属性为 false。

阅读全文 »

Android LaunchMode 总结

Android 中的 LaunchMode 是一个比较基础的知识点,关于这块之前每次都是先用现学,然后学了之后又忘了,现在把 LaunchMode 的规律记录下来以备后用。

需要了解的知识点

在讲 LaunchMode 之前,需要了解一下几点知识:

  1. task 有属性 affinity,Activity 有属性 taskAffinity
  2. 可以存在两个 affinity 一样的 task;
  3. 一个 Activity 的 taskAffnity 默认值为 package name,如果有指定值就会设为指定值
    阅读全文 »