Blog

dangling pointer

Content #

可以说,即使经过了八十一难,终于成为了 C 语言绝世高手,我们还是逃不过复杂的堆上对象引用关系导致的 dangling pointer:

你看,在这张图中,当 B 被 free 掉之后,应用程序依然可能会使用指向 B 的指针,这就是比较典型的 dangling pointer 问题,堆上的对象依赖关系可能会非常复杂。所以,我们要正确地写出 free 逻辑,还得先把对象图给画出来。

Viewpoint #

From #

大咖助阵|曹春晖:聊聊 Go 语言的 GC 实现

pkg errors包是如何输出错误信息及堆栈信息的

Content #

github.com/pkg/errors 是怎么实现输出错误信息和堆栈信息的呢?

它利用了 fmt 包的一个特性。fmt 包在打印 error 之前会判断当前打印的对象是否实现了 Formatter 接口,这个 formatter 接口只有一个 format 方法。如果要输出的对象实现了这个 Formatter 接口,则调用对象的 Format 方法来打印信息:

type Formatter interface {
    Format(f State, c rune)
}

而 github.com/pkg/errors 中提供的各种初始化 error 方法(包括 errors.New)封装了一个 fundamental 结构,这个结构就是实现了 Formatter 接口:

// fundamental is an error that has a message and a stack, but no caller.
type fundamental struct {
        msg string
        *stack
}

这个 fundamental 结构中带着 error 的信息和堆栈信息。并且实现了 Format 方法。在 Format 方法中,判断调用 fmt.Printf 函数的第一个参数,如果是 +v,则打印错误内容和堆栈信息,如果是 v 或者 s,则打印错误内容,如果是 q,则打印转义后的信息:

...

cbw与cwd

Content #

同一个负数,其表现形式略有差别。比如十进制数-3,它在8 位运算中是 11111101,即0xFD;在16 位运算中,则是1111111111111101,即0xFFFD。在计算机中,-3 是用0 减去3 得到的,在8 位运算中只能保留结果的低8 位,即 11111101(0xFD);在16 位运算中只能保留结果的低16 位,即 1111111111111101(0xFFFD)。很显然,一个8 位的有符号数,要想用16 位的形式来表示,只需将其最高位,也就是用来辨别符号的那一位(几乎所有的书上都称之为符号位,实际上这并不严谨),扩展到高8 位即可。

处理器专门设计了两条指令来做这件事:cbw(Convert Byte to Word)和 cwd(Convert Word to Double-word)。

cbw #

cbw 没有操作数,操作码为98。它的功能是,将寄存器AL 中的有符号数扩展到整个AX。如果AL 中的内容为01001111,那么执行该指令后,AX 中的内容为 0000000001001111;如果AL 中的内容为10001101,执行该指令后,AX 中的内容为1111111110001101。

cwd #

cwd 也没有操作数,操作码为99。它的功能是,将寄存器AX 中的有符号数扩展到DX:AX。

如果AX 中的内容为0100111101111001,那么执行该指令后,DX 中的内容为 0000000000000000,AX 中的内容不变;

如果AX 中的内容为1000110110001011,那么执行该指令后,DX 中的内容为 1111111111111111,AX 中的内容同样不变。

Viewpoint #

From #

溢出标志OF

Content #

同样的运算,从无符号数和有符号数的视角来看,判断是否溢出是不一样的。但是,在所有的情况下,处理器都不可能知道你的意图,不知道你进行的是有符号数运算,还是无符号数运算。

处理器提供的溢出标志OF的意思是,假定你进行的是有符号数运算,如果运算结果是正确的,那么OF=0,否则OF=1。

mov ah, 0xff add ah, 2 从有符号数的角度来看,是-1 和2 相加,结果为1,未溢出,故OF=0。从无符号数的角度来看,是255+2,会发生溢出。

Viewpoint #

From #

用方向标志DF控制数据传送的方向

Content #

movsb 和 movsw 指令执行时,

  1. 原始数据串的段地址由DS 指定,偏移地址由SI 指定,简写为DS:SI;
  2. 要传送到的目的地址由ES:DI 指定;
  3. 传送的字节数(movsb)或者字数(movsw)由CX指定。
  4. 还要指定是正向传送还是反向传送。

正向传送:

  1. 指传送操作的方向是从低地址端到高地址端;
  2. 每传送一个字节(movsb)或者一个字(movsw),SI 和DI 加1 或者加2;

反向传送:

  1. 反向传送方向是从高地址端到低地址端。
  2. 每传送一个字节(movsb)或者一个字(movsw)时,SI 和DI 减去 1 或者减去2。

不管是正向传送还是反向传送,也不管每次传送的是字节还是字,每传送一次,CX 的内容自动减一。

方向标志DF(Direction Flag):通过将这一位清零或者置1,就能控制movsb 和movsw 的传送方向。方向标志清零指令cld是个无操作数指令,与其相反的是置方向标志指令std。 cld 指令将DF 标志清零,以指示传送是正方向的。 std 指令,它将DF标志置位 1。此时,传送的方向是从高地址到低地址。

Viewpoint #

From #

ZF零标志位的实现原理

Content #

当处理器执行一条算术或者逻辑运算指令后,算术逻辑部件送出的结果除了送到指令中指定位置(目的操作数指定的位置)外,还送到一个或非门。

或非门的输入全为0 时,输出为1;输入不全为0,或者全部为1 时,输出为0。或非门的输出送到一个触发器,这就是标志寄存器的ZF 位。

Viewpoint #

From #

显卡文本模式

Content #

所有在个人计算机上使用的显卡,在加电自检之后都会把自己初始化到80×25 的文本模式。在这种模式下,屏幕上可以显示25 行,每行80 个字符,每屏总共 2000 个字符。

0xB8000~0xBFFFF (共320KB)这段物理地址空间就是留给显卡的,用来显示文本。如果显卡出了毛病,计算机就无法通过加电自检过程,计算机是无法启动的,更不要说加载并执行主引导扇区的内容了。

屏幕上的每个字符对应着显存中的两个连续字节,前一个是字符的ASCII 代码,后面是字符的显示属性,包括字符颜色(前景色)和底色(背景色)。

如图所示,字符“H”的ASCII 代码是0x48,其显示属性是0x07;字符“e”的 ASCII 代码是0x65,其显示属性是0x07。

字符的显示属性(1 字节)分为两部分,低4 位定义的是前景色,高4 位定义的是背景色。色彩主要由R、G、B 这3 位决定,可以由红(R)、绿(G)、蓝(B)三原色来配出其他所有颜色。K 是闪烁位,为0 时不闪烁,为1 时闪烁;I 是亮度位,为0时正常亮度,为1 时呈高亮。

下表给出了背景色和前景色的所有可能值。

Viewpoint #

From #

跨代引用假说

Content #

跨代引用假说(Intergenerational Reference Hypothesis)跨代引用相对于同代引用来说仅占极少数。

依据这条假说,我们就不应再为了少量的跨代引用去扫描整个老年代,也不必浪费空间专门记录每一个对象是否存在及存在哪些跨代引用,只需在新生代上建立一个全局的数据结构(该结构被称为“记忆集”,Remembered Set),这个结构把老年代划分成若干小块,标识出老年代的哪一块内存会存在跨代引用。此后当发生Minor GC时,只有包含了跨代引用的小块内存里的对象才会被加入到GC Roots进行扫描。

虽然这种方法需要在对象改变引用关系(如将自己或者某个属性赋值)时维护记录数据的正确性,会增加一些运行时的开销,但比起收集时扫描整个老年代来说仍然是划算的。

Viewpoint #

From #

为什么学习中的困难是必要的

Content #

发明了“合意困难”这个词的比约克夫妇认为,困难之所以必要的原因是什么?困难能触发编码和检索过程,从而支持学习、理解以及记忆。

Viewpoint #

From #

让群体中的每个人都用付出者的方式行事

Content #

在与人打交道时,付出者进行真诚性筛选,在与获取者交易时采取互利者的方式,通过这些做法来保护自己,这是完全合理的。但是,在群体当中,还有另外一种做法,可以让付出者确保自己不被人利用。请问是什么方法?

让群体中的每个人都用付出者的方式行事。

这种策略在贾森·盖勒和莉莉安·鲍尔的故事中已经有所预示,他们直接要求接受过他们指导的人,将这种做法传递下去,继续指导更加年轻的同事,以此来作为回报。如果一个群体发展出了一种付出的常规模式,成员就会遵守这种常规模式,做出付出行为,即使他们在其他地方更倾向于做获取者,或是互利者。这减少了付出的风险:当每个人都做出贡献时,蛋糕就更大了,而付出者做出的贡献,也不会总是远远大于他们得到的回报。

Viewpoint #

From #